《Entity Framework 6 Recipes》中文翻译——第九章EntityFramework在N层架构程序中的应用(七)

在WCF服务中的序列化代理

问题

  您有一个从查询返回的动态代理对象,你想要把它像POCO对象已经进行序列化。在序列化基于实体对象的POCO(普通旧CLR对象)时,实体框架会自动生成一个动态生成的派生类型为每个POCO实体对象,称为动态代理对象。代理对象覆盖了许多的POCO类虚拟属性去注册钩子为展现功能,如更改跟踪和相关实体的延迟加载。

解决方案

  假设你有如下一个模型

  我们将使用代理数据契约解析器反序列化一个代理对象为POCO对象在WCF客户端。执行以下操作:

  1、创建一个新的WCF服务应用程序。添加ADO.NET Entity Data Model,选择Client表

  2、打开实体框架生成的客户端POCO类,并添加虚拟关键字为每个属性,这样做会导致实体框架生成动态代理类。

public class Client
{
    public virtual int ClientId { get; set; }
    public virtual string Name { get; set; }
    public virtual string Email { get; set; }
}

  我们需要的数据协定序列化程序使用代理数据契约解析类为WCF服务的客户端将客户端Client代理转换为Client实体。为此,我们将创建一个操作行为属性和应用属性到GetClient()服务方法。记住,代理数据契约解析类驻留在实体框架命名空间。

public class ApplyProxyDataContractResolverAttribute : Attribute, IOperationBehavior
    {
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
            
        }

        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
                      operationDescription.Behaviors.Find <DataContractSerializerOperationBehavior>();
            dataContractSerializerOperationBehavior.DataContractResolver =
                      new ProxyDataContractResolver();

        }

        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
                      operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
            dataContractSerializerOperationBehavior.DataContractResolver =
                       new ProxyDataContractResolver();
        }

        public void Validate(OperationDescription operationDescription)
        {
        }
    }

  4、修改Iservice.cs的代码如下

 [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        void InsertTestRecord();

        [OperationContract]
        Client GetClient();

        [OperationContract]
        void Update(Client client);
    }

  5、实现Iservice中的接口在IService1.svc.cs 中

public class Service1 : IService1
    {
        [ApplyProxyDataContractResolverAttribute]
        public Client GetClient()
        {
            using (var context = new EntitiesContext())
            {
                context.Configuration.LazyLoadingEnabled = false;
                return context.Clients.Single();
            }

        }
        [ApplyProxyDataContractResolverAttribute]
        public void InsertTestRecord()
        {
            using (var context = new EntitiesContext())
            {
                context.Database.ExecuteSqlCommand("delete from Client");
                context.Database.ExecuteSqlCommand(@"insert into
                      Client(Name, Email)
                      values ('Jerry Jones','jjones@gmail.com')");

            }
        }
        [ApplyProxyDataContractResolverAttribute]
        public void Update(Client client)
        {
            using (var context = new EntitiesContext())
            {
                context.Entry(client).State =
                       EntityState.Modified;
                context.SaveChanges();
            }
        }
    }

6、在解决方案中添加一个新的控制台应用程序项目作为我们的客户端,同时添加WCF服务引用

class Program
    {
        static void Main(string[] args)
        {
            using (var serviceClient = new Service1Client())
            {
                serviceClient.InsertTestRecord();
                var client = serviceClient.GetClient();
                Console.WriteLine("Client is: {0} at {1}",
                                    client.Name, client.Email);
                client.Name = "Alex Park";
                client.Email = "Alex P@hotmail.com";
                serviceClient.Update(client);
                client = serviceClient.GetClient();
                Console.WriteLine("Client changed to: {0} at {1}",
                                    client.Name, client.Email);

            }
        }
}

结果:

  微软建议使用WCF POCO对象简化实体对象的序列化。然而,如果你的应用程序是使用POCO对象改变的通知(你有虚拟和显著的性能导航属性集合的类型是ICollection),然后实体框架会创建查询返回的实体动态代理。

 

posted on 2016-07-25 19:01  yunxia_云霞  阅读(171)  评论(0编辑  收藏  举报