不得不在这里吐槽一下,年终总结的高难度,高挑战性,历时三天我也没能想出个所以然,道是把学习笔记完工了,情何以堪  Dot Net FrameWork 4.0 学习笔记(6)_FrameWork    


    WCF 数据服务 (以前称为“ADO.NET Data Services”)是 .NET Framework 的一个组件。可以使用此组件创建一些服务,利用开放式数据协议 (OData) 来借助具象状态传输 (REST) 语义通过 Web 或 Intranet 公开和使用数据。OData  将数据公开为可通过 URI 寻址的资源。可使用 GET、PUT、POST 和 DELETE 这些标准 HTTP 谓词来访问和更改数据。OData 使用Entity Data Model的实体关系约定,将资源公开为通过关联相关的实体集.   --- 引用自MSDN



    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)
                return 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)
        {
            return null;
        }


        public System.IO.Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality,     System.Data.Services.DataServiceOperationContext operationContext)
        {
            throw new NotImplementedException();
        }


        public string ResolveType(string entitySetName, System.Data.Services.DataServiceOperationContext operationContext)
        {
            throw new NotImplementedException();
        }


        // 流缓冲大小
        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

    // 使用 WCF 数据服务 可以定义基于任意类的数据模型,前提是这些类作为实现 IQueryable 接口的对象公开

    // 自定义数据展示

    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();        }    }}