介紹
ADO.NET Data Services 1.5 的新增功能
* 支持服務端的 RowCount - 獲取指定實體集合的成員數(只返回一個整型值,而不會返回實體集合)
* 支持服務端的分頁 - 服務端可以返回分頁後的數據,並且在其中還可以包含全部數據總數
* 支持服務端的 Select - 返回的結果只包括 Select 的字段
* 支持大數據傳輸 BLOB(binary large object)
* 支持自定義數據服務
示例
1、服務端 RowCount 的 Demo
MyDataService.svc.cs
代碼
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
namespace DataAccess.DataServices.Service
{
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyDataService : DataService<MyEntity.AdventureWorksEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
// SetEntitySetPageSize(string name, int size) - 新增的方法。用於提供分頁後的數據
// string name - 指定需要用於分頁的實體集合
// int size - 分頁的頁大小
config.SetEntitySetPageSize("Products", 5);
}
}
}
RowCount.aspx.cs
代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.DataServices
{
public partial class RowCount : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyDataServiceProxy.AdventureWorksEntities context = new MyDataServiceProxy.AdventureWorksEntities(new Uri("http://localhost:9046/DataServices/Service/MyDataService.svc/"));
// 支持服務端的 RowCount - 獲取指定實體集合的成員數(只返回一個整型值,而不會返回實體集合 )
var productCount = context.Products.Count();
Response.Write(productCount.ToString());
}
}
}
/*
$count - 返回 RowCount,即對應集合的成員數(只返回一個整型值,而不會返回實體集合)
http://localhost:9046/DataServices/Service/MyDataService.svc/Products/$count
$inlinecount=none - 只返回實體集合(分頁後的數據)
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$inlinecount=none
$inlinecount=allpages - 在返回實體集合的基礎上(分頁後的數據),其中還會包括一個實體集合成員數(分頁前的數據)的字段
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$inlinecount=allpages
*/
2、服務端分頁的 Demo
MyDataService.svc.cs
代碼
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
namespace DataAccess.DataServices.Service
{
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyDataService : DataService<MyEntity.AdventureWorksEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
// SetEntitySetPageSize(string name, int size) - 新增的方法。用於提供分頁後的數據
// string name - 指定需要用於分頁的實體集合
// int size - 分頁的頁大小
config.SetEntitySetPageSize("Products", 5);
}
}
}
Paging.aspx.cs
代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.DataServices
{
public partial class Paging : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyDataServiceProxy.AdventureWorksEntities context = new MyDataServiceProxy.AdventureWorksEntities(new Uri("http://localhost:9046/DataServices/Service/MyDataService.svc/"));
// 支持服務端的分頁 - 服務端可以返回分頁後的數據,並且在其中還可以包含全部數據總數
// 服務端代碼:config.SetEntitySetPageSize("Products", 5); 表示每頁最多 5 條數據
// 客戶端代碼:通過 Skip() 方法來控制需要跳過的記錄數
var products = context.Products.Skip(10);
foreach (var product in products)
{
Response.Write(product.ProductID.ToString() + "<br />");
}
}
}
}
/*
$skip=[int] - 指定需要跳過的記錄數
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$skip=10
$inlinecount=none - 只返回實體集合(分頁後的數據)
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$inlinecount=none
$inlinecount=allpages - 在返回實體集合的基礎上(分頁後的數據),其中還會包括一個實體集合成員數(分頁前的數據)的字段
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$inlinecount=allpages
*/
3、服務端 Select 的 Demo
MyDataService.svc.cs
代碼
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
namespace DataAccess.DataServices.Service
{
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyDataService : DataService<MyEntity.AdventureWorksEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
// SetEntitySetPageSize(string name, int size) - 新增的方法。用於提供分頁後的數據
// string name - 指定需要用於分頁的實體集合
// int size - 分頁的頁大小
config.SetEntitySetPageSize("Products", 5);
}
}
}
QueryProjection.aspx.cs
代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.DataServices
{
public partial class QueryProjection : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyDataServiceProxy.AdventureWorksEntities context = new MyDataServiceProxy.AdventureWorksEntities(new Uri("http://localhost:9046/DataServices/Service/MyDataService.svc/"));
// 支持服務端的 Select - 返回的結果只包括 Select 的字段
var products = context.Products.Select(p => new { ProductID = p.ProductID, Name = p.Name });
foreach (var product in products)
{
Response.Write(product.ProductID.ToString() + ": " + product.Name + "<br />");
}
}
}
}
/*
$select=[column1,column2,column3,...] - 返回的實體集合數據中只包括指定的字段
http://localhost:9046/DataServices/Service/MyDataService.svc/Products/?$select=ProductID,Name
*/
4、BLOB 的 Demo
BLOBService.svc.cs
代碼
/*
ADO.NET Data Services 1.5 - 新增了對大數據傳輸 BLOB(binary large object)的支持
需要在概念模型(ConceptualModels)中的相關實體上增加屬性“m:HasStream="true" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"”
*/
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.IO;
namespace DataAccess.DataServices.Service
{
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class BLOBService : DataService<MyEntity.AdventureWorksEntities>, IServiceProvider
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
}
public object GetService(Type serviceType)
{
if (serviceType != typeof(System.Data.Services.Providers.IDataServiceStreamProvider))
return null;
// 調用服務的時候,如果指定了需要流式傳輸大數據對象,則通過我們自定義的流式文件傳輸對象去處理
return new ProductPhotoStreamProvider();
}
}
/// <summary>
/// 自定義的一個流式文件傳輸類,需要實現 System.Data.Services.Providers.IDataServiceStreamProvider 接口
/// </summary>
public class ProductPhotoStreamProvider : System.Data.Services.Providers.IDataServiceStreamProvider
{
/// <summary>
/// 獲取流。將某個實體的某個屬性以流類型的方式返回
/// </summary>
/// <param name="entity">相關的實體</param>
/// <param name="operationContext">當前數據服務請求的上下文</param>
/// <returns></returns>
public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
{
if (entity as MyEntity.Product == null)
return null;
int productId = (entity as MyEntity.Product).ProductID;
using (var context = new MyEntity.AdventureWorksEntities())
{
var product = context.Products.First(p => p.ProductID == productId);
var stream = new MemoryStream(product.ThumbNailPhoto);
return stream;
}
}
public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
{
return null;
}
// 流的內容類型
public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
{
return "image/jpeg";
}
public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
{
return null;
}
// 流的緩沖區大小
public int StreamBufferSize
{
get { return 64; }
}
public void DeleteStream(object entity, DataServiceOperationContext operationContext)
{
throw new NotImplementedException();
}
public System.IO.Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
{
throw new NotImplementedException();
}
public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
{
throw new NotImplementedException();
}
}
}
BLOB.aspx
代碼
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="BLOB.aspx.cs" Inherits="DataAccess.DataServices.BLOB" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<!--
查看元數據 - http://localhost:9046/DataServices/Service/BLOBService.svc/$metadata
-->
<!--
Products(714) - 在 Products 集合中取主鍵為 714 的實體
$value - 取流數據
-->
<img src="http://localhost:9046/DataServices/Service/BLOBService.svc/Products(714)/$value" alt="image" />
</asp:Content>
5、自定義數據服務的 Demo
CustomDataService.svc.cs
代碼
/*
ADO.NET Data Services 1.5 - 新增了對自定義數據服務的支持
*/
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
namespace DataAccess.DataServices.Service
{
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class CustomDataService : DataService<OrderContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("Orders", EntitySetRights.All);
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
}
}
/// <summary>
/// 數據上下文
/// </summary>
public class OrderContext
{
static List<Order> _orders;
static List<Product> _products;
static OrderContext()
{
_orders = new List<Order>
{
new Order { OrderId = 0, Customer="webabcd"},
new Order { OrderId = 1, Customer="webabcdefg"}
};
_products = new List<Product>
{
new Product { ProductId = 0, ProductName="wii", Price=100 },
new Product { ProductId = 1, ProductName="xbox360", Price=200 },
new Product { ProductId = 2, ProductName="ps3", Price = 300 },
new Product { ProductId = 3, ProductName="nds", Price=50 },
new Product { ProductId = 4, ProductName="psp", Price=100 }
};
_orders[0].Items.Add(_products[0]);
_orders[0].Items.Add(_products[1]);
_orders[1].Items.Add(_products[2]);
_orders[1].Items.Add(_products[3]);
_orders[1].Items.Add(_products[4]);
}
public IQueryable<Order> Orders
{
get { return _orders.AsQueryable<Order>(); }
}
public IQueryable<Product> Products
{
get { return _products.AsQueryable<Product>(); }
}
}
/*
* DataServiceKeyAttribute() - 指定主鍵字段
* EntityPropertyMapping() - 實體屬性到 ATOM 字段的映射,以便生成一個友好格式的 Feed
*/
[EntityPropertyMapping("Customer", SyndicationItemProperty.AuthorName, SyndicationTextContentKind.Plaintext, true)]
[DataServiceKeyAttribute("OrderId")]
public class Order
{
public int OrderId { get; set; }
public string Customer { get; set; }
private List<Product> _items;
public List<Product> Items
{
get
{
if (_items == null)
_items = new List<Product>();
return _items;
}
set
{
_items = value;
}
}
}
[DataServiceKeyAttribute("ProductId")]
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int Price { get; set; }
}
}
CustomDataService.aspx.cs
代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.DataServices
{
public partial class CustomDataService : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 使用自定義數據服務提供的服務
CustomDataServiceProxy.OrderContext context = new CustomDataServiceProxy.OrderContext(new Uri("http://localhost:9046/DataServices/Service/CustomDataService.svc/"));
var orders = context.Orders;
foreach (var order in orders)
{
Response.Write(order.OrderId.ToString() + "<br />");
}
}
}
}
注:
以 URI 語法的方式查詢 ADO.NET 數據服務的形式如下:
http://[Url]/[ServiceName]/[EntityName]/[NavigationOptions]?[QueryOptions]
詳細語法參看 MSDN