共用方式為


逐步解說:使用 WCF 序列化 POCO Proxy (Entity Framework)

POCO Proxy 型別無法由 Windows Communication Foundation (WCF) 直接序列化或還原序列化,因為 DataContractSerializer 序列化引擎只能序列化及還原序列化已知型別。 Proxy 型別不是已知型別。 如需詳細資訊,請參閱使用 POCO 實體 (Entity Framework)主題中的<序列化 POCO Proxy>一節。 若要將 POCO Proxy 序列化為 POCO 實體,在序列化期間請使用 ProxyDataContractResolver 類別來將 Proxy 型別對應至 POCO 型別。

此主題中的範例會示範如何指示 DataContractSerializer 在服務作業中透過定義套用至服務作業的屬性類別來使用 ProxyDataContractResolver 類別,該類別會在內部使用 ProxyDataContractResolver 來將 Proxy 型別對應至 POCO 型別。 它還示範如何將這個屬性類別與 WCF 應用程式中服務合約之一部分的方法產生關聯。

本主題中的範例使用 HOW TO:定義 POCO 實體 (Entity Framework) 中所定義之 POCO 類別,以及 HOW TO:自訂模型與對應檔以搭配自訂物件運作 (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 檔案。 以滑鼠右鍵按一下設計工具介面並選取 [屬性]。 在 [屬性] 視窗中,選取 [程式碼產生策略] 屬性並選取 [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 的專案中。 將以 AdventureWorks Model 為基礎的可序列化 POCO 類別中的程式碼加入至檔案。 其中包含實體類型和物件內容定義。

  9. 編譯專案。

建立和設定 WCF 專案。

  1. 在與類別庫專案 (名為 POCOAdventureWorksService) 相同的方案中,建立一個 WCF Service Application 專案。

  2. 加入 System.Data.Entity 程式庫的參考。

  3. 加入 POCOAdventureWorksModel 專案的參考,這就是用以定義模型的位置。

  4. 將連接字串加入至 .config 檔,如此 Entity Framework 執行階段才可以尋找中繼資料。 開啟 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 Proxy,用戶端還是會收到純粹的 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)