您的數據合同表示您的服務公開向外界公開的API。一旦您的服務開始被客戶使用,您希望避免對該合同進行重大更改 - 特別是如果您的服務被您的控制之外的客戶所使用。當然,如果你的服務只是爲了「內部」使用,那麼你對此有一些靈活性。
隨着「編程抽象 - 不是實現」的理念 - 您的WCF服務的數據(和服務)契約在面向服務的上下文中提供抽象,類似於面向對象的世界中的接口。
如果您使用.dll共享您的數據合同,那麼在我看來 - 您無法解決這個事實,即您需要單獨的類來表示您的服務數據合同和數據模型。使用像AutoMapper這樣的映射工具可以顯着減少轉換代碼的數量。如果您試圖在數據合同中聲明額外的信息(比如說通過數據成員的屬性) - 最終會泄露有關您的數據訪問方法的信息到已發佈的二進制文件中。如果將來您切換到另一種數據訪問方法 - 甚至是NoSQL數據庫,會發生什麼?您對數據合同的更改可能會破壞使用舊版本二進制文件的現有客戶端。
在我提出替代方案之前 - 讓我說,以上是我將在全部的情況下做的事情。您的數據模型和您的服務API表示根本不同的野獸,由於不同的因素,這些野獸會相互獨立地變化。儘管如此,它們通常看起來很相似,但其中使用和可能改變的環境完全不同。
現在對於一個黑客...
如果您通過MEX端點發布服務的API,在Visual Studio中(或真svcutil.exe的)產生代理 - 客戶端獲取自己的服務版本和數據合同。在服務方面,你可以做這樣的事情:
[DataContract]
public class Entity
{
[DataMember]
public int? Temp { get; set; }
[Description]
public int? DbTemp { get; set; }
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context)
{
Temp = DbTemp;
}
}
當Entity
實例從數據庫填充,DbTemp
屬性設置。只有當實例被序列化以準備發送給客戶端時,纔會填充Temp
屬性。
當你的客戶創造從MEX端點代理和數據合同中,Entity
數據合同看起來是這樣的:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Entity", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
[System.SerializableAttribute()]
public partial class Entity : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private System.Nullable<int> TempField;
[global::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
get {
return this.extensionDataField;
}
set {
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public System.Nullable<int> Temp {
get {
return this.TempField;
}
set {
if ((this.TempField.Equals(value) != true)) {
this.TempField = value;
this.RaisePropertyChanged("Temp");
}
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
不是你的數據訪問實現的嗅!
最後 - 請注意,您可以通過發佈.dlls完成上述技巧 - 您只需發佈上面包含「精簡」數據合同的.dll文件。但是,這意味着您必須有效管理Entity
的兩個不同版本 - 您的服務在內部使用的版本和發佈的.dll的版本。如果這些不同步 - 祝你好運,調試那個!
當你在這裏說額外的類時,你的意思是上面用'Description'屬性顯示的* auxiliary *類嗎?我的意思是,你想在代碼中避免使用這個類嗎? – Halvard
@Halvard是的,確切地說,我的壞英語感到抱歉。 –
因此,您不想向數據協定添加任何額外的內容(如屬性),並且您不想創建新類,並且DataContract和Entity之間沒有使用傳統映射:您唯一的選擇是創建一個存儲在文件中的映射(例如XML)。 – Aidin