Пошаговое руководство. Сериализация прокси-сущностей POCO с помощью WCF (платформа Entity Framework)

Тип прокси POCO не может быть непосредственно сериализован или десериализован платформой Windows Communication Foundation (WCF), поскольку модуль сериализации DataContractSerializer способен сериализовать и десериализовать только известные типы. Тип прокси не является известным типом. Дополнительные сведения см. в подразделе «Сериализация прокси-сущностей POCO» раздела Работа с сущностями POCO (платформа Entity Framework). Для сериализации прокси-сущностей POCO как сущностей POCO воспользуйтесь классом ProxyDataContractResolver для сопоставления прокси-типов с типами POCO во время сериализации.

Пример в данном разделе демонстрирует настройку DataContractSerializer для использования класса ProxyDataContractResolver в операциях службы путем определения класса атрибута, который применяется к операциям службы и внутренним образом использует ProxyDataContractResolver для сопоставления прокси-типов с типами POCO. Он также демонстрирует связывание класса атрибутов с методами, являющимися частью контракта службы приложения WCF.

В примерах из этого раздела используются классы POCO, определенные в разделе Как определить сущности POCO (платформа Entity Framework), и модель данных на основе AdventureWorks, определенная в разделе Как настроить файлы моделирования и сопоставления для работы с пользовательскими объектами (платформа Entity Framework).

Чтобы создать проект библиотеки классов, содержащий классы POCO, выполните следующие действия.

  1. Создайте новый проект библиотеки классов с именем POCOAdventureWorksModel.

  2. Удалите файл исходного кода по умолчанию, добавленный к проекту.

  3. Добавьте пустую модель с именем AdventureWorksModel. Сведения о создании пустой модели см. в подразделе «Создание пустого EDMX-файла» раздела How to: Create a New .edmx File. Измените модель, следуя шагам, описанным в разделе Пользовательский EDMX-файл AdventureWorks (платформа Entity Framework).

  4. Отключите создание кода для EDMX-файла. Откройте EDMX-файл в конструкторе сущностей (ADO.NET Entity Data Model Designer). Щелкните правой кнопкой мыши в области конструктора и выберите пункт «Свойства». В окне Свойства выберите свойство Стратегия создания кода и укажите значение None. Если окно Свойства не отображается, нажмите клавишу F4.

  5. Добавьте файл App.Config к проекту библиотеки классов. Щелкните правой кнопкой мыши проект POCOAdventureWorksModel, выберите пункт Добавить, затем Новый элемент.

  6. В диалоговом окне Добавление нового элемента выберите Общие шаблоны, затем Файл конфигурации приложения. Скопируйте следующий код между тегами configuration в файле конфигурации приложения. При необходимости измените значение Data Source.

    <connectionStrings>
      <add name="AdventureWorksEntities" 
          connectionString="metadata=res://*/AdventureWorksModel.csdl|res://*/AdventureWorksModel.ssdl|res://*/AdventureWorksModel.msl;
              provider=System.Data.SqlClient;provider connection string=&quot;
              Data Source=(local);Initial Catalog=AdventureWorks;
              Integrated Security=True;MultipleActiveResultSets=True&quot;" 
          providerName="System.Data.EntityClient" />
    </connectionStrings>
    
  7. Добавьте ссылку на библиотеку System.Runtime.Serialization. Эта библиотека нужна для WCF DataContract и для атрибутов DataMember, используемых для сериализуемых типов сущности.

  8. Добавьте новый класс к проекту с именем POCOClasses. Добавьте код в файл Сериализуемые классы POCO на основе модели AdventureWorks. Он содержит тип сущности и определения контекстного объекта.

  9. Скомпилируйте проект.

Создание и настройка проекта WCF

  1. Создайте проект WCF Service Application в том же решении, что и проект библиотеки классов с именем POCOAdventureWorksService.

  2. Добавьте ссылку на библиотеку System.Data.Entity.

  3. Добавьте ссылку на проект POCOAdventureWorksModel, в котором определена модель.

  4. Добавьте строку соединения в файл конфигурации CONFIG, чтобы среда выполнения Entity Framework могла найти метаданные. Откройте файл app.config в проекте POCOAdventureWorksModel, скопируйте элемент connectionStrings и добавьте его как дочерний элемент элемента configuration файла Web.config.

  5. Создайте новый класс и назовите его ApplyDataContractResolverAttribute.

  6. Добавьте следующие пространства имен в начало файла:

    using System.Data.Objects;
    using System.ServiceModel.Description;
    using System.ServiceModel.Channels;
    
  7. Замените код, созданный для нового класса, следующим кодом.

    public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
    {
        public ApplyDataContractResolverAttribute()
        {
        }
    
        public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
        {
        }
    
        public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
        {
            DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
                description.Behaviors.Find<DataContractSerializerOperationBehavior>();
            dataContractSerializerOperationBehavior.DataContractResolver =
                new ProxyDataContractResolver();
        }
    
        public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
        {
            DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior =
                description.Behaviors.Find<DataContractSerializerOperationBehavior>();
            dataContractSerializerOperationBehavior.DataContractResolver =
                new ProxyDataContractResolver();
        }
    
        public void Validate(OperationDescription description)
        {
            // Do validation.
        }
    }
    
  8. Откройте файл интерфейса службы. По умолчанию он называется IService1.

  9. Добавьте пространство имен POCOAdventureWorksModel в начало файла. Это пространство имен, в котором определяются типы POCO.

  10. Замените код, определяющий файл интерфейса службы, следующим кодом.

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [ApplyDataContractResolver]
        void UpdateOrder(Order updated);
    
        [OperationContract]
        [ApplyDataContractResolver]
        Order GetOrder(int OrderID);
    }
    
  11. Откройте исходный код службы. По умолчанию он называется Service1.srv.cs (или .vb).

  12. Добавьте пространство имен POCOAdventureWorksModel в начало файла.

  13. Замените код, определяющий класс службы, следующим кодом.

    public class Service1 : IService1
    {
        public void UpdateOrder(Order updated)
        {
            using (POCOAdventureWorksEntities context =
                new POCOAdventureWorksEntities())
            {
                // Attach the original order to the context by querying the database.
                // Alternatively, you can require that the updated object be returned along with the original object from the client.
                // This means the client would need to clone the original object. 
                Order original = context.Orders.SingleOrDefault(o => o.SalesOrderID == updated.SalesOrderID);
                // Apply changes to the order object.
                context.Orders.ApplyCurrentValues(updated);
    
                context.SaveChanges();
            }
        }
        public Order GetOrder(int OrderID)
        {
            using (POCOAdventureWorksEntities context = new POCOAdventureWorksEntities())
            {
                // You can disable the proxy creation
                // by setting context.ContextOptions.ProxyCreationEnabled to false
                context.ContextOptions.LazyLoadingEnabled = false;
                // The order was created as a POCO proxy object. 
                // But it will be recieved on the client as a pure POCO.
                Order order = context.Orders.SingleOrDefault(o => o.SalesOrderID == OrderID);
                return order;
            }
        }
    }    
    
  14. Скомпилируйте проект.

Тестирование службы

  1. Создайте консольное приложение. В качестве имени проекта укажите POCOAdventureWorksTest.

  2. Добавьте ссылку на проект POCOAdventureWorksModel.

  3. Добавьте ссылку на службу POCOAdventureWorksService. В Обозревателе решений щелкните правой кнопкой мыши нужную папку, затем выберите Добавить ссылку на службу.

  4. Откройте файл app.config и добавьте в файл строку соединения. Откройте файл app.config для элемента POCOAdventureWorksModel, скопируйте элемент connectionStrings и добавьте его в качестве дочернего элемента для элемента configuration файла Web.config.

  5. Откройте файл, содержащий функцию main.

  6. Добавьте следующие пространства имен, в которых определены типы служб и POCO, в начало файла.

    Service1Client client = new Service1Client();
    
    int orderId = 43680;
    Order order = client.GetOrder(orderId);
    Console.WriteLine(order.DueDate);
    // Modify order.
    order.DueDate = DateTime.Now;
    // Update order in the database.
    client.UpdateOrder(order);
    
  7. Замените код следующим кодом. Заметьте, что хотя служба и способна выполнять сериализацию прокси-сущностей POCO, клиент получает пустые объекты POCO.

    Service1Client client = new Service1Client();
    
    int orderId = 43680;
    Order order = client.GetOrder(orderId);
    Console.WriteLine(order.DueDate);
    // Modify order.
    order.DueDate = DateTime.Now;
    // Update order in the database.
    client.UpdateOrder(order);
    

См. также

Основные понятия

Сериализация объектов (платформа Entity Framework)