WCF數(shù)據(jù)契約變更基本應(yīng)用技巧分析
在WCF中,數(shù)據(jù)契約的應(yīng)用是一個十分重要而且基礎(chǔ)的操作技術(shù)。那么今天我們將會在這篇文章中為大家詳細(xì)講解一下有關(guān)WCF數(shù)據(jù)契約變更的相關(guān)知識,以方便大家在實際應(yīng)用中獲得一些幫助。#t#
Person DataContract 定義了兩個屬性:FirstName 和LastName。如果客戶端引用了這個服務(wù),而你后來將LastName改成SurName,實際上客戶端不會中斷,但是在客戶端的代理類上的LastName屬性會顯示為空的。這是因為當(dāng)客戶端解串信息到Person類的時候,不會找到任何叫做Lastname的元素。
這個簡單的WCF數(shù)據(jù)契約變更不會引起客戶端的錯誤,但它會導(dǎo)致更嚴(yán)重的問題:一個意外的行為。這個錯誤很容易跟蹤,但是跟蹤變更行為是非常困難的。
這個簡單的例子說明為什么任何服務(wù)變更和它們后續(xù)的影響是至關(guān)重要的。除非你自己知道利用你的web服務(wù)的每個客戶端應(yīng)用程序,否則變更會是個災(zāi)難。作為一名開發(fā)人員,你需要盡一切努力使你的客戶端避免變更的出現(xiàn)。
首先,你可以應(yīng)用一些***的方法來幫助客戶端免于內(nèi)部變更。WCF數(shù)據(jù)契約變更的更新版本如以下所示:
- [DataContract(Namespace="http://types.mycompany.com/2009/05/25",
Name="PersonContract")]- public class Person : IExtensibleDataObject
- {
- private string _firstName = string.Empty;
- private string _lastName = string.Empty;
- private ExtensionDataObject _extensionData;
- [DataMember(Name="FirstName")]
- public string FirstName
- {
- get { return _firstName; }
- set { _firstName = value; }
- }
- [DataMember(Name="LastName")]
- public string LastName
- {
- get { return _lastName; }
- set { _lastName = value; }
- }
- public ExtensionDataObject ExtensionData
- {
- get { return _extensionData; }
- set { _extensionData = value; }
- }
- }
在DataContract上增加的Namespace, Name和Order參數(shù)以及DataMember屬性控制DataContractSerializer的行為。當(dāng)服務(wù)的reference被添加的時候,這個增加的東西生成客戶端代理。Name參數(shù)讓serializer使用所指出的值,而不是實際公布的成員或是屬性的名字。這個方法在沒有影響客戶端的情況下允許變更的內(nèi)部執(zhí)行。例如,考慮以下的WCF數(shù)據(jù)契約變更:
- [DataMember(Name="LastName")]
- public string SurName
- {
- get { return _lastName; }
- set { _lastName = value; }
- }
將"FirstName" 改成"SurName"的屬性名字變更不會中斷現(xiàn)有的客戶端,因為客戶端使用的Name參數(shù)仍然是"FirstName."。只是內(nèi)部執(zhí)行被該改變了。
第二個顯著的變化是增加了IExtensibleDataObject接口。執(zhí)行這個接口允許客戶端保留在契約中沒有明確定義的數(shù)據(jù)。這似乎看上去沒什么用,但是在客戶端希望執(zhí)行示例Person對象并返回它的情況下,客戶端可以保留新的數(shù)據(jù)項目。例如,用以下不會強(qiáng)迫現(xiàn)有的客戶端進(jìn)行更新的新成員來更新PersonContract:
- [DataMember(Name = "MiddleName", Order = 3)]
- public string SurName
- {
- get { return _middleName; }
- set { _middleName = value; }
- }
實際上,這個成員通過往返過程的服務(wù),允許現(xiàn)存的客戶端保留放在"MiddleName"中的值。執(zhí)行IExtensibleDataObject對你的WCF數(shù)據(jù)契約變更未來的論證是一個有益的方法。
請記住,實際上客戶端對一個外部構(gòu)架有驗證信息的選擇權(quán)。(對WCF應(yīng)用程序添加信息構(gòu)架驗證的詳細(xì)討論,請閱讀此文章this article)。因此,當(dāng)處理數(shù)據(jù)契約的變更時你有兩種情況需要考慮:有構(gòu)架驗證和沒有構(gòu)架驗證。
當(dāng)客戶端添加構(gòu)架驗證的時候,在數(shù)據(jù)契約中進(jìn)行添加,變更或是減去任何項目將導(dǎo)致驗證的失敗。所以,在嚴(yán)格的構(gòu)架驗證被使用的情況下,不能對契約進(jìn)行改變。相反,你需要創(chuàng)建一個完整的新的契約并在這個契約中使用不同的命名空間來顯示新版本。
例如,從執(zhí)行的角度來看,你需要兩個單獨的服務(wù)終端使這兩個版本可用:
Original Version: [DataContract(Namespace="http://schemas.mycompany.com/2009/05/25")]
New Version: [DataContract(Namespace=http://schemas.mycompany.com/2009/06/18)]
幸運(yùn)的是,嚴(yán)格的構(gòu)架驗證不是默認(rèn)的行為。這意思是在沒有中斷服務(wù)端的情況下,你可以添加或刪除數(shù)據(jù)成員。但是,由于先前所討論的有不預(yù)期的行為會產(chǎn)生,刪除數(shù)據(jù)成員不是一個好主意。另一方面,添加一個數(shù)據(jù)成員是很容易做到的,而且consumers會忽略它們還沒有意識到的外部成員。
關(guān)鍵的做法是使用DataMember屬性(先前討論過的)的Order參數(shù)。使用這個參數(shù)可以告訴serializers什么樣的順序(每個成員的)可以出現(xiàn)在XML中
來自基礎(chǔ)類型的成員
沒有order參數(shù)(按字母順序排列)的成員
有order參數(shù)(按值排列)的成員
WCF數(shù)據(jù)契約變更考慮的***情況是改變一個數(shù)據(jù)成員的類型。這種情況下,***的方法是創(chuàng)建一個新版本的數(shù)據(jù)契約并帶有新的服務(wù)契約,執(zhí)行和終端。