不得不在這裡吐槽一下,年終總結的高難度,高挑戰性,曆時三天我也沒能想出個是以然,道是把學習筆記完工了,情何以堪
ADO.NET Data Services 1.5(WCF Data Services) 的新增功能
1,支援服務端的 RowCount - 擷取指定實體集合的成員數(隻傳回一個整型值,而不會傳回實體集合)
2,支援服務端的分頁 - 服務端可以傳回分頁後的資料,并且在其中還可以包含全部資料總數
3,支援服務端的 Select - 傳回的結果隻包括 Select 的字段
4,支援大資料傳輸 BLOB(binary large object)
5,支援自定義資料服務
1. RowCount (當然新玩意就要配置點新協定了 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;)
rowCount隻有在資料服務協定第二版本才能使用
$count - 傳回 RowCount,即對應集合的成員數(隻傳回一個整型值,而不會傳回實體集合)
http://localhost:12345/WcfDataService1.svc/EmployeeInfo/$count
$inlinecount=none - 隻傳回實體集合(分頁後的資料)
http://localhost:12345/WcfDataService1.svc/EmployeeInfo/$inlinecount=none
$inlinecount=allpages - 在傳回實體集合的基礎上(分頁後的資料),其中還會包括一個實體集合成員數(分頁前的資料)的字段
http://localhost:9046/DataServices/Service/MyDataService.svc/Products?$inlinecount=allpages
2. 資料服務分頁
// 設定伺服器分頁方式
config.SetEntitySetPageSize("EmployeeInfo", 5);
// 用戶端則使用
http://localhost:12345/WcfDataService1.svc/EmployeeInfo?$skip=10
// 當然可以使用rowcount中的$inlinecount來擷取資料
3. select字段及多參數
$select=[column1,column2,column3,...] - 傳回的實體集合資料中隻包括指定的字段
http://localhost:12345/WcfDataService1.svc/EmployeeInfo/?$select=EmployeeId,EmployeeName/&$inlinecount=allpages
4. BLOB大資料對象
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.Data.Services.Providers 此命名空間之下
public class WcfDataService1 : DataService<HrmsDBEntities>,IServiceProvider
{
// 僅調用此方法一次以初始化涉及服務範圍的政策。
public static void InitializeService(DataServiceConfiguration config)
{
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
// 設定規則以指明哪些實體集和服務操作是可見的、可更新的,等等。
// config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); // 設定通路範圍
// config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); // 設定服務謂詞通路
config.SetEntitySetAccessRule("EmployeeInfo", EntitySetRights.AllRead | EntitySetRights.AllWrite);
}
public object GetService(Type serviceType)
if (serviceType != typeof(IDataServiceStreamProvider))
{
return null;
}
// 調用服務的時候,如果指定了需要流式傳輸大資料對象,則通過我們自定義的流式檔案傳輸對象去處理
return new StreamProvider();
}
// 資料服務流提供實作類,需要實作IDataServiceStreamProvider接口
public class StreamProvider : IDataServiceStreamProvider
public void DeleteStream(object entity, System.Data.Services.DataServiceOperationContext operationContext)
throw new NotImplementedException();
// 傳回流
public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext)
if (entity as EmployeeInfo == null)
string employeeId = (entity as EmployeeInfo).EmployeeId;
using (var context = new HrmsDBEntities())
var employee = context.EmployeeInfo.First(p => p.EmployeeId == employeeId);
var stream = new MemoryStream(byte.Parse(employee.EmployeePicture));
return stream;
public Uri GetReadStreamUri(object entity, System.Data.Services.DataServiceOperationContext operationContext)
return null;
// 傳回内容
public string GetStreamContentType(object entity, System.Data.Services.DataServiceOperationContext operationContext)
return "image/jpeg";
public string GetStreamETag(object entity, System.Data.Services.DataServiceOperationContext operationContext)
public System.IO.Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, System.Data.Services.DataServiceOperationContext operationContext)
public string ResolveType(string entitySetName, System.Data.Services.DataServiceOperationContext operationContext)
// 流緩沖大小
public int StreamBufferSize
get { return 64; }
// 擷取EmployeeInfo表上主鍵為zx0000000007的值
調用擷取 http://localhost:12345/WcfDataService1.svc/EmployeeInfo(zx0000000007)/$value
5. 自定義資料服務呢,就是将EF的實作過程我們手寫一遍啦
要注意将資料上下文對象實作IQueryable接口,DataServiceKeyAttribute() 指定主鍵字段
EntityPropertyMapping() 實體屬性到 ATOM 字段(可以了解為外鍵字段)的映射,以便生成一個友好格式的 Feed
// 設定規則以指明哪些實體集和服務操作是可見的、可更新的,等等。
// config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); // 設定通路範圍
// config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); // 設定服務謂詞通路
config.SetEntitySetAccessRule("EmployeeInfo", EntitySetRights.AllRead | EntitySetRights.AllWrite);
ps:就如開頭說的,如何将CLR類型資料轉換成具有平台互操互性資料,我們可以利用WCF DataService
WCF DataService巧妙利用了REST架構來實作對資源的通路,也利用自身SOAP特點将資料完美展現
到此為止我們的4.0新特性歸結到此,其實4.0的東西遠不止這些,這些隻是一些常用的...
補記: 摘自MSDN
// 自定義資料展示
using System;
using System.Collections.Generic; using System.Data.Services; using System.Data.Services.Common; using System.Linq; namespace CustomDataServiceClient { [DataServiceKeyAttribute("OrderId")] public class Order { public int OrderId { get; set; } public string Customer { get; set; } public IList<Item> Items { get; set; } } [DataServiceKeyAttribute("Product")] public class Item { public string Product { get; set; } public int Quantity { get; set; } } public partial class OrderItemData { static IList<Order> _orders; static IList<Item> _items; static OrderItemData() { _orders = new Order[]{ new Order(){ OrderId=0, Customer = "Peter Franken", Items = new List<Item>()}, new Order(){ OrderId=1, Customer = "Ana Trujillo", Items = new List<Item>()}}; _items = new Item[]{ new Item(){ Product="Chai", Quantity=10 }, new Item(){ Product="Chang", Quantity=25 }, new Item(){ Product="Aniseed Syrup", Quantity = 5 }, new Item(){ Product="Chef Anton's Cajun Seasoning", Quantity=30}}; _orders[0].Items.Add(_items[0]); _orders[0].Items.Add(_items[1]); _orders[1].Items.Add(_items[2]); _orders[1].Items.Add(_items[3]); } public IQueryable<Order> Orders { get { return _orders.AsQueryable<Order>(); } } public IQueryable<Item> Items { get { return _items.AsQueryable<Item>(); } } } public class OrderItems : DataService<OrderItemData> { public static void InitializeService(IDataServiceConfiguration config) { config.SetEntitySetAccessRule("Orders", EntitySetRights.All); config.SetEntitySetAccessRule("Items", EntitySetRights.All); } } }
// LINQ TO SQL實體 using System; using System.ComponentModel; using System.Collections; using System.Linq; using System.Reflection; using System.Data.Linq; using System.Data.Linq.Mapping; using System.Data.Services; using System.Data.Services.Common; namespace NorthwindService { // Define the key properties for the LINQ to SQL data classes. [DataServiceKeyAttribute("CustomerID")] public partial class Customer { } [DataServiceKeyAttribute("ProductID")] public partial class Product { } [DataServiceKeyAttribute("OrderID")] public partial class Order { } [DataServiceKeyAttribute("OrderID", "ProductID")] public partial class Order_Detail { } // Define the IUpdatable implementation for LINQ to SQL. public partial class NorthwindDataContext : IUpdatable { // Creates an object in the container. object IUpdatable.CreateResource(string containerName, string fullTypeName) { Type t = Type.GetType(fullTypeName, true); ITable table = GetTable(t); object resource = Activator.CreateInstance(t); table.InsertOnSubmit(resource); return resource; } // Gets the object referenced by the resource. object IUpdatable.GetResource(IQueryable query, string fullTypeName) { object resource = query.Cast<object>().SingleOrDefault(); // fullTypeName can be null for deletes if (fullTypeName != null && resource.GetType().FullName != fullTypeName) throw new ApplicationException("Unexpected type for this resource."); return resource; } // Resets the value of the object to its default value. object IUpdatable.ResetResource(object resource) { Type t = resource.GetType(); MetaTable table = Mapping.GetTable(t); object dummyResource = Activator.CreateInstance(t); foreach (var member in table.RowType.DataMembers) { if (!member.IsPrimaryKey && !member.IsDeferred && !member.IsAssociation && !member.IsDbGenerated) { object defaultValue = member.MemberAccessor.GetBoxedValue(dummyResource); member.MemberAccessor.SetBoxedValue(ref resource, defaultValue); } } return resource; } // Sets the value of the given property on the object. void IUpdatable.SetValue(object targetResource, string propertyName, object propertyValue) { MetaTable table = Mapping.GetTable(targetResource.GetType()); MetaDataMember member = table.RowType.DataMembers.Single(x => x.Name == propertyName); member.MemberAccessor.SetBoxedValue(ref targetResource, propertyValue); } // Gets the value of a property on an object. object IUpdatable.GetValue(object targetResource, string propertyName) { MetaTable table = Mapping.GetTable(targetResource.GetType()); MetaDataMember member = table.RowType.DataMembers.Single(x => x.Name == propertyName); return member.MemberAccessor.GetBoxedValue(targetResource); } // Sets the related object for a reference. void IUpdatable.SetReference( object targetResource, string propertyName, object propertyValue) { ((IUpdatable)this).SetValue(targetResource, propertyName, propertyValue); } // Adds the object to the related objects collection. void IUpdatable.AddReferenceToCollection( object targetResource, string propertyName, object resourceToBeAdded) { PropertyInfo pi = targetResource.GetType().GetProperty(propertyName); if (pi == null) throw new Exception("Can't find property"); IList collection = (IList)pi.GetValue(targetResource, null); collection.Add(resourceToBeAdded); } // Removes the object from the related objects collection. void IUpdatable.RemoveReferenceFromCollection( object targetResource, string propertyName, object resourceToBeRemoved) { PropertyInfo pi = targetResource.GetType().GetProperty(propertyName); if (pi == null) throw new Exception("Can't find property"); IList collection = (IList)pi.GetValue(targetResource, null); collection.Remove(resourceToBeRemoved); } // Deletes the resource. void IUpdatable.DeleteResource(object targetResource) { ITable table = GetTable(targetResource.GetType()); table.DeleteOnSubmit(targetResource); } // Saves all the pending changes. void IUpdatable.SaveChanges() { SubmitChanges(); } // Returns the actual instance of the resource represented // by the resource object. object IUpdatable.ResolveResource(object resource) { return resource; } // Reverts all the pending changes. void IUpdatable.ClearChanges() { // Raise an exception as there is no real way to do this with LINQ to SQL. // Comment out the following line if you'd prefer a silent failure throw new NotSupportedException(); } }}
本文轉自My_King1 51CTO部落格,原文連結:http://blog.51cto.com/apprentice/1360547,如需轉載請自行聯系原作者