介紹
以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