다음을 통해 공유


연습: WCF를 사용하여 POCO 프록시 Serialize(Entity Framework)

DataContractSerializer serialization 엔진이 알려진 형식만 serialize 및 deserialize할 수 있기 때문에 WCF(Windows Communication Foundation)에서 POCO 프록시 형식을 직접 serialize 또는 deserialize할 수 없습니다. 프록시 형식은 알려진 형식이 아닙니다. 자세한 내용은 POCO 엔터티 사용(Entity Framework) 항목의 POCO 프록시 Serialize 단원을 참조하십시오. POCO 프록시를 POCO 엔터티로 serialize하려면 ProxyDataContractResolver 클래스를 사용하여 serialization 중에 프록시 형식을 POCO 형식으로 매핑합니다.

이 항목의 예제에서는 서비스 작업에 적용될 특성 클래스를 정의하여 서비스 작업에서 ProxyDataContractResolver 클래스를 사용하도록 DataContractSerializer에 지시하는 방법을 보여 줍니다. 이 특성 클래스는 내부적으로 ProxyDataContractResolver를 사용하여 프록시 형식을 POCO 형식으로 매핑합니다. 또한 WCF 응용 프로그램에서 서비스 계약의 일부인 메서드와 특성 클래스를 연결하는 방법도 보여 줍니다.

이 항목의 예제에서는 방법: POCO 엔터티 정의(Entity Framework)에 정의된 POCO 클래스와 방법: 사용자 지정 개체를 사용할 수 있도록 모델링 및 매핑 파일 사용자 지정(Entity Framework)에 정의된 AdventureWorks 기반 데이터 모델을 사용합니다.

POCO 클래스가 포함된 클래스 라이브러리 프로젝트를 만들려면

  1. POCOAdventureWorksModel이라는 새로운 클래스 라이브러리 프로젝트를 만듭니다.

  2. 프로젝트에 추가된 기본 소스 코드 파일을 제거합니다.

  3. AdventureWorksModel이라는 빈 모델을 추가합니다. 빈 모델을 만들려면 How to: Create a New .edmx File 항목의 빈 .edmx 파일을 만들려면 단원을 참조하십시오. 사용자 지정 AdventureWorks .edmx 파일(Entity Framework)의 단계에 따라 모델을 수정합니다.

  4. .edmx 파일의 코드 생성 기능을 사용하지 않도록 설정합니다. ADO.NET Entity Data Model Designer(Entity Designer)에서 .edmx 파일을 엽니다. 디자이너 화면을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 속성 창에서 Code Generation Strategy 속성을 선택하고 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 라이브러리에 대한 참조를 추가합니다. 이 라이브러리는 serialize 가능한 엔터티 형식에서 사용되는 WCF DataContractDataMember 특성에 필요합니다.

  8. 새 클래스를 POCOClasses라는 프로젝트에 추가합니다. AdventureWorks 모델 기반의 serialize 가능한 POCO 클래스의 코드를 파일에 추가합니다. 여기에는 엔터티 형식과 개체 컨텍스트 정의가 포함됩니다.

  9. 프로젝트를 컴파일합니다.

WCF 프로젝트를 만들고 구성하려면

  1. POCOAdventureWorksService라는 클래스 라이브러리 프로젝트와 동일한 솔루션에 WCF Service Application 프로젝트를 만듭니다.

  2. System.Data.Entity 라이브러리에 대한 참조를 추가합니다.

  3. 모델이 정의되는 POCOAdventureWorksModel 프로젝트에 대한 참조를 추가합니다.

  4. Entity Framework 런타임에서 메타데이터를 찾을 수 있도록 .config 파일에 연결 문자열을 추가합니다. POCOAdventureWorksModel 프로젝트의 app.config 파일을 열고 connectionStrings 요소를 복사하여 Web.config 파일에 있는 configuration 요소의 자식 요소로 추가합니다.

  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 파일을 열고 연결 문자열을 파일에 추가합니다. POCOAdventureWorksModel의 app.config 파일을 열고 connectionStrings 요소를 복사하여 Web.config 파일에 있는 configuration 요소의 자식 요소로 추가합니다.

  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 프록시를 serialize할 수 있지만 클라이언트가 순수한 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);
    

참고 항목

개념

개체 Serialize(Entity Framework)