介紹
以Northwind為示例數據庫,演示ADO.NET Data Services(數據服務)
DataService - ADO.NET 數據服務的主入口點。 T 為數據源類名
IDataServiceConfiguration.SetEntitySetAccessRule(string name, EntitySetRights rights) - 為指定實體集設置訪問規則
QueryInterceptorAttribute - 聲明在方法上的查詢攔截器
DataServiceContext - 數據服務的上下文
DataServiceQuery - 以指定的 URI 語法查詢數據服務
示例
服務端
Service.cs
using System;
using System.Data.Services;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Web;
using VS2008SP1.Business;
using System.Linq.Expressions;
// DataService<T> - ADO.NET 數據服務的主入口點。 T 為數據源類名
public class Service : DataService<VS2008SP1.Business.NorthwindEntities>
{
// 初始化涉及服務范圍的策略(僅調用一次)
public static void InitializeService(IDataServiceConfiguration config)
{
/**//*
* IDataServiceConfiguration.SetEntitySetAccessRule(string name,
EntitySetRights rights) - 為指定實體集設置訪問規則
* name - 實體集名稱(* 為全部)
* rights - 設置對指定實體集的操作權限
[System.Data.Services.EntitySetRights 枚舉]
* EntitySetRights.None - 權限為:無任何權限
* EntitySetRights.All - 權限為:全部權限
* EntitySetRights.ReadSingle - 權限為:只能讀取數據集內的某一條數據
* EntitySetRights.ReadMultiple - 權限為:可讀取數據集內的全部數據
* EntitySetRights.WriteAppend - 權限為:插入
* EntitySetRights.WriteReplace - 權限為:更新
* EntitySetRights.WriteDelete - 權限為:刪除
* EntitySetRights.WriteMerge - 權限為:合並數據
* EntitySetRights.AllRead - 權限為:全部可讀
* EntitySetRights.AllWrite - 權限為:全部可寫
*/
config.SetEntitySetAccessRule("*", EntitySetRights.All);
// config.SetEntitySetAccessRule("*", EntitySetRights.AllRead |
EntitySetRights.AllWrite);
}
/**//*
* QueryInterceptorAttribute - 聲明在方法上的查詢攔截器
* 方法名任意(不帶參數),返回值必須為一個 Expression<Func<T,
bool>> 表達式,T 為需要過濾的實體集類名
*/
[QueryInterceptor("Orders")]
public Expression<Func<Orders, bool>> FilterOrders()
{
// 本例為無論在任何情況下,返回的 Orders 都是 ContactName 為 Paul Henriot 的
Orders
return o => o.Customers.ContactName == "Paul Henriot";
}
}
1、添加、查詢、更新和刪除的Demo
Demo.aspx
<%@ Page Title="添加、查詢、更新和刪除的Demo" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Demo.aspx.cs" Inherits="DataServices_Demo" %> <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> <div style="margin: 10px;"> CategoryName:<asp:TextBox ID="txtCategoryName" runat="server" /> Description:<asp:TextBox ID="txtDescription" runat="server" /> <asp:Button ID="btnAddCategory" runat="server" Text="添加產品類別" OnClick="btnAddCategory_Click" /> </div> <div style="margin: 10px;"> <asp:GridView ID="GridView1" DataKeyNames="CategoryID" runat="server" AutoGenerateColumns="false" OnRowDeleting="GridView1_RowDeleting" OnRowCancelingEdit="GridView1_RowCancelingEdit" OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating" OnSelectedIndexChanged="GridView1_SelectedIndexChanged"> <Columns> <asp:BoundField DataField="CategoryID" HeaderText="ID" ReadOnly="true" /> <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" /> <asp:BoundField DataField="Description" HeaderText="Description" /> <asp:CommandField ShowSelectButton="True" ShowEditButton="True" ShowDeleteButton="True"> </asp:CommandField> </Columns> </asp:GridView> </div> <div style="margin: 10px;"> <asp:GridView ID="GridView2" runat="server"> </asp:GridView> </div> </asp:Content>
Demo.aspx.cs
// 客戶端用到的只有以下兩個類
// System.Data.Services.Client.DataServiceContext - 數據服務的上下文
// System.Data.Services.Client.DataServiceQuery - 以指定的 URI 語法查詢數據服務
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MyDataService;
public partial class DataServices_Demo : System.Web.UI.Page
{
// ADO.NET 數據服務的地址
Uri _uri = new Uri("http://localhost:7002/DataServices/Service.svc/",
UriKind.Absolute);
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
BindData();
}
}
void BindData()
{
// NorthwindEntities - 繼承自 DataServiceContext ,其構造函數的參數為數據服務
的 URI 地址
NorthwindEntities ctx = new NorthwindEntities(_uri);
// 將 System.Data.Services.Client.DataServiceQuery<Categories> 綁定到
Gridview1
GridView1.DataSource = ctx.Categories;
GridView1.DataBind();
}
protected void btnAddCategory_Click(object sender, EventArgs e)
{
NorthwindEntities ctx = new NorthwindEntities(_uri);
Categories category = new Categories();
category.CategoryName = txtCategoryName.Text;
category.Description = txtDescription.Text;
// DataServiceContext.Timeout - 超時時間
// DataServiceContext.MergeOption - 當前數據上下文與數據服務的數據的同步選項
[System.Data.Services.Client.MergeOption 枚舉]
// AppendOnly - 追加。默認值
// OverwriteChanges - 以新結果為准
// PreserveChanges - 以原結果為准
// NoTracking - 取消變更跟蹤,不會使用 ObjectStateManager,減少執行查
詢的時間,所有返回的實體將是分離的狀態(detached state)
ctx.MergeOption = System.Data.Services.Client.MergeOption.AppendOnly;
ctx.AddToCategories(category);
for (int i = 0; i < 10; i++)
{
var product = new Products() { ProductName = "測試用" + i.ToString()
};
product.Categories = category;
ctx.AddToProducts(product);
// DataServiceContext.SetLink(Object source, string sourceProperty,
Object target) - 在指定對象上創建新的連接,Added狀態,SaveChanges() 的時候會一起發送到數據服
務。多對一關系
// source - 源對象
// sourceProperty - 源對象上的屬性,用於標識目標對象的類型
// target - 目標對象
ctx.SetLink(product, "Categories", category);
// DataServiceContext.AddLink(Object source, string sourceProperty,
Object target) - 在指定對象上創建新的連接,Added狀態,SaveChanges() 的時候會一起發送到數據服
務。一對多關系
// DataServiceContext.DeleteLink(Object source, string
sourceProperty, Object target) - 在指定的對象上刪除連接,Deleted狀態,SaveChanges() 的時候會
一起發送到數據服務
}
// DataServiceContext.SaveChanges() - 將所有更新保存到相關存儲區中
// SaveChangesOptions.Batch - 一個 http 提交所有操作
// SaveChangesOptions.ContinueOnError - 一個 http 一個操作,某操作出
錯仍將處理後續操作(不能與 Batch 共存)
// SaveChangesOptions.ReplaceOnUpdate -
// SaveChangesOptions.None - 出錯則停止
ctx.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
Page.ClientScript.RegisterStartupScript(this.GetType(), "js", "alert
('CategoryID: " + category.CategoryID + "');", true);
GridView1.EditIndex = -1;
BindData();
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
NorthwindEntities ctx = new NorthwindEntities(_uri);
var categoryId = (int)GridView1.DataKeys[e.RowIndex].Value;
var category = ctx.Categories.Where(p => p.CategoryID ==
categoryId).First();
// DataServiceContext.LoadProperty(Object entity, string propertyName) - 加載
指定對象的指定實體屬性
// entity - 包含要加載的實體屬性的實體
// propertyName - 需要加載的實體屬性的名稱
ctx.LoadProperty(category, "Products");
foreach (var product in category.Products)
{
ctx.DeleteObject(product);
}
ctx.DeleteObject(category);
ctx.SaveChanges();
GridView1.EditIndex = -1;
BindData();
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
NorthwindEntities ctx = new NorthwindEntities(_uri);
var categoryId = (int)GridView1.SelectedDataKey.Value;
// 查找當前選中的類別下的產品集合
var products = ctx.Products.Where(p => p.Categories.CategoryID ==
categoryId);
// 將 System.Linq.IQueryable<Products> 綁定到 GridView2
GridView2.DataSource = products;
GridView2.DataBind();
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
NorthwindEntities ctx = new NorthwindEntities(_uri);
var categoryId = (int)GridView1.DataKeys[e.RowIndex].Value;
var category = ctx.Categories.Where(p => p.CategoryID ==
categoryId).First();
category.CategoryName = ((TextBox)GridView1.Rows[e.RowIndex].Cells
[1].Controls[0]).Text;
category.Description = ((TextBox)GridView1.Rows[e.RowIndex].Cells
[2].Controls[0]).Text;
ctx.UpdateObject(category);
ctx.SaveChanges();
GridView1.EditIndex = -1;
BindData();
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
BindData();
}
protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs
e)
{
GridView1.EditIndex = -1;
BindData();
}
}
2、其他知識點
Demo2.aspx
<%@ Page Title="其它" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Demo2.aspx.cs" Inherits="DataServices_Demo2" %> <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> <div id="result" runat="server"> </div> </asp:Content>
Demo2.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MyDataService;
using System.Data.Services.Client;
public partial class DataServices_Demo2 : System.Web.UI.Page
{
// ADO.NET 數據服務的地址
Uri _uri = new Uri("http://localhost:7002/DataServices/Service.svc/",
UriKind.Absolute);
protected void Page_Load(object sender, EventArgs e)
{
// 以 URI 語法的方式查詢 ADO.NET 數據服務
Demo();
// 異步方式查詢 ADO.NET 數據服務
Demo2();
// 演示查詢攔截器的 Demo
Demo3();
// 演示以 JSON 作為響應格式的 Demo
Demo4();
}
void Demo()
{
DataServiceContext ctx = new DataServiceContext(_uri);
// 以 URI 語法的方式查詢 ADO.NET 數據服務,詳細語法參看 MSDN
// http://[Url]/[ServiceName]/[EntityName]/[NavigationOptions]?[QueryOptions]
DataServiceQuery<Categories> categories =
ctx.CreateQuery<Categories>("/Categories");
foreach (var c in categories)
{
result.InnerHtml += c.CategoryID + ",";
}
result.InnerHtml += "<br /><br />";
}
void Demo2()
{
DataServiceContext ctx = new DataServiceContext(_uri);
DataServiceQuery<Categories> query = ctx.CreateQuery<Categories>
("/Categories");
// 異步方式查詢 ADO.NET 數據服務
query.BeginExecute(
delegate(IAsyncResult ar)
{
foreach (var c in query.EndExecute(ar))
{
result.InnerHtml += c.CategoryID + ",";
}
result.InnerHtml += "<br /><br />";
},
null);
}
void Demo3()
{
NorthwindEntities ctx = new NorthwindEntities(_uri);
// 因為設置了查詢攔截器,所以只能收到 ContactName 為 Paul Henriot 的 Orders
foreach (var o in ctx.Orders)
{
result.InnerHtml += o.OrderID + ",";
}
result.InnerHtml += "<br /><br />";
}
void Demo4()
{
System.Net.WebClient client = new System.Net.WebClient();
// 需要以 json 格式返回結果的話,需要設置以下 header
client.Headers.Add("accept", "application/json");
// client.Headers.Add("accept", "application/xml"); xml/atom 格式
// client.Headers.Add("accept", "*/*"); xml/atom 格式,默認值
result.InnerHtml += HttpUtility.HtmlEncode(client.DownloadString(_uri));
}
}
本文配套源碼:http://www.bianceng.net/dotnet/201212/806.htm