首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

談 WCF Data Contract (四):資料合約版本控制與往返問題解決

     編輯:關於.NET

前言

SOA 系統中,服務與用戶端獨立演進是常態。資料合約 (Data Contract) 版本變更時,如何確保現有用戶端不中斷?本文透過實例探討 WCF 如何處理單方面新增資料成員的版本控制,以及解決往返問題的 IExtensibleDataObject 機制。

範例架構

  • 服務端:Artech.DataContractVersioning.Service,定義 Order 資料合約 (OrderID、OrderDate、SupplierID)。
  • 用戶端:Artech.DataContractVersioning.Client,定義 CustomOrder,透過屬性對應服務端合約,並額外新增 ShippingAddress。

資料合約定義

服務端 Order


[DataContract(Namespace = "https://artech.datacontractversioning")]
public class Order
{
    [DataMember(Order = 0)] public Guid OrderID { get; set; }
    [DataMember(Order = 1)] public DateTime OrderDate { get; set; }
    [DataMember(Order = 2)] public Guid SupplierID { get; set; }
}

用戶端 CustomOrder (初版)


[DataContract(Name = "Order", Namespace = "https://artech.datacontractversioning")]
public class CustomOrder
{
    [DataMember(Order = 0, Name = "OrderID")] public Guid OrderNo { get; set; }
    [DataMember(Order = 2, Name = "SupplierID")] public Guid SupplierNo { get; set; }
    [DataMember(Order = 1)] public DateTime OrderDate { get; set; }
}

透過 Name、Namespace、Order 屬性,雙方 CLR 型別雖不同,但資料合約完全匹配。

問題:單方面新增成員導致資料遺失

用戶端在 CustomOrder 新增 ShippingAddress:


[DataMember(Order = 3)] public string ShippingAddress { get; set; }

呼叫服務端 Process(Order order) (直接回傳接收的 Order) 後,ShippingAddress 遺失:

ShippingAddress 遺失

原因:服務端 Order 無此成員,反序列化時忽略未知資料。若該物件再流向其他服務,將造成往返問題:資料在多跳傳遞中逐漸遺失擴充欄位。

解決方案:實作 IExtensibleDataObject

在服務端 Order 實作 IExtensibleDataObject:


[DataContract(Namespace = "https://artech.datacontractversioning")]
public class Order : IExtensibleDataObject
{
    [DataMember(Order = 0)] public Guid OrderID { get; set; }
    [DataMember(Order = 1)] public DateTime OrderDate { get; set; }
    [DataMember(Order = 2)] public Guid SupplierID { get; set; }

    public ExtensionDataObject ExtensionData { get; set; }
}

IExtensibleDataObject 僅定義一個 ExtensionData 屬性 (型別 ExtensionDataObject),用於儲存反序列化時遇到的未識別資料。

驗證結果

再次執行用戶端,ShippingAddress 完整保留:

資料完整往返

偵錯檢視 ExtensionData 內容,確認包含 ShippingAddress:

ExtensionData 內容

核心機制總結

場景未實作 IExtensibleDataObject實作 IExtensibleDataObject
用戶端新增成員服務端反序列化時捨棄服務端保留於 ExtensionData
服務端回傳物件遺失擴充資料原樣回傳擴充資料
多跳傳遞 (A→B→C)逐層遺失完整保留

最佳實務建議

  • 服務端資料合約預設實作 IExtensibleDataObject,確保向前相容。
  • 用戶端亦建議實作,以應對服務端新增成員的情況。
  • Order 屬性指定成員序列化順序,配合版本演進更穩健。
  • 避免移除或重命名現有 DataMember,改為標記 IsRequired=false (預設) 並新增成員。

結語

WCF 透過 IExtensibleDataObject 优雅解決資料合約版本演進中的往返問題,是建構可長期演進 SOA 系統的關鍵機制。下一篇將探討集合與字典型別的資料合約支援。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved