2013-10-25 16 views
3

我有一個數據契約:如何避免在將數據庫表映射到數據契約時創建附加類?

[DataContract] 
public class Entity 
{ 
    [DataMember] 
    public int? Temp 
    { 
     get; 
     set; 
    } 
    //other properties 
} 

我需要建立基於數據庫表的信息Entity對象。我必須使用SqlDataReader(需求),然後將列映射到實體屬性。我創建使用Description屬性映射,它描述了輔​​助類:

public class Entity 
{ 
    [Description("TempColumnName")] 
    public int? Temp 
    { 
     get; 
     set; 
    } 
    //other properties 
} 

我怎樣才能避免這種情況下,附加類的創作?我認爲使用數據契約屬性名稱或裝飾數據契約與其他屬性是一個壞主意。你有什麼建議嗎?

+0

當你在這裏說額外的類時,你的意思是上面用'Description'屬性顯示的* auxiliary *類嗎?我的意思是,你想在代碼中避免使用這個類嗎? – Halvard

+0

@Halvard是的,確切地說,我的壞英語感到抱歉。 –

+0

因此,您不想向數據協定添加任何額外的內容(如屬性),並且您不想創建新類,並且DataContract和Entity之間沒有使用傳統映射:您唯一的選擇是創建一個存儲在文件中的映射(例如XML)。 – Aidin

回答

3

您的數據合同表示您的服務公開向外界公開的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的版本。如果這些不同步 - 祝你好運,調試那個!

0

將數據合同中的描述屬性,WCF不會使用它,無論過程中需要說明可以使用它:

[DataContract] 
public class Entity 
{ 
    [DataMember] 
    [Description("TempColumnName")] 
    public int? Temp 
    { 
     get; 
     set; 
    } 
    //other properties 
} 
+0

數據契約是數據契約,我認爲用別的東西超重它並不是很酷......而且這也可能給某個人一個壞主意,試圖檢查客戶端代碼中'描述'屬性的存在。 –

+0

@QuéPadre類屬性是一個類屬性,將更多的屬性放在一個不會超重*的地方出現故障。根據你的帖子的要求是不要有一個輔助影子類;爲此,這個建議就是這樣做的。如果實現隱藏是目標,那麼對這個輔助類的需求是一個需求,並不是一件好事。 – OmegaMan

+2

沒有向合約添加垃圾是有正當理由的,尤其是因爲它會將公共合約永久地綁定到底層數據庫。 –