2012-11-09 28 views
4

比方說,我有以下C#類,我想成爲不可變的。您只能通過使用參數化的構造函數來設置它。POCO's,ORM和不變性。如何讓他們一起工作?

public class InsulineInjection 
{ 
    private InsulineInjection() 
    { 
     // We don't want to enable a default constructor. 
    } 

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) 
    { 
     this.Remark = remark; 
     this.DateTime = dateTime; 
     this.Millilitre = millilitre; 
    } 

    public string Remark { get; private set; } 
    public DateTime DateTime { get; private set; } 
    public Millilitre Millilitre { get; private set; } 
} 

現在我想用一個ORM來創建這個POCO。但是,據我所見,所有.NET ORM的期望屬性都是可訪問的,並且有一個公共構造函數可以創建此POCO。所以我不得不改變我的POCO這個:

public class InsulineInjection 
{ 
    public InsulineInjection() 
    { 
    } 

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) 
    { 
     this.Remark = remark; 
     this.DateTime = dateTime; 
     this.Millilitre = millilitre; 
    } 

    public string Remark { get; set; } 
    public DateTime DateTime { get; set; } 
    public Millilitre Millilitre { get; set; } 
} 

然而,這使我的POCO又易變。有人使用它可以簡單地改變任何屬性後,這是不是我想要的。

至於我能看到它,我可以以兩種不同的方式解決這個問題:

  1. 寫我自己的數據訪問層(或修改ORM),以便能夠使用構造函數創建正確的POCO實例我創建。
  2. 創建某種映射器。讓ORM創建簡單的DTO對象,並使用映射器在合適的時間將DTO對象轉換爲我的POCO。

我傾向於解決方案2.有人有如何做到這一點的例子嗎?還是有人比我上面描述的更好的解決方案?

+0

#2聽起來很可能。像automapper這樣的組件可以派上用場。什麼客戶/你的應用程序層需要你的類型是不可變的? –

+0

爲什麼你想要你的數據庫對象是不可變的?查詢會很好,但是如何計劃更新數據庫中的值?我和下一個人一樣對不可改變的類型有很大的喜愛,但是這對於一個可變類型來說似乎是一個合適的地方。 – Servy

+0

此代碼僅僅是一個小型業餘愛好項目的例子。它應該表示您可以添加新的注射劑。但是,一旦添加它就不能再進行修改。 當然,我可以在UI中對它進行編碼,但是如果POCO中表示此功能,我發現它會更加透徹。 – Sardaukar

回答

4

許多OR只要有一個默認的構造函數和setter方法(不管它們是公共的或不是,他們只是必須存在)

所以這不會工作(沒有默認構造函數)/小姐工作:

public class InsulineInjection 
{ 
    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) 
    { 
     this.Remark = remark; 
     this.DateTime = dateTime; 
     _millilitre = millilitre; 
    } 

    public string Remark { get; set; } 
    public DateTime DateTime { get; set; } 
    public Millilitre Millilitre { get { return _millilitre; } } 
} 

或本(沒有setter最後屬性)

public class InsulineInjection 
{ 
    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) 
    { 
     this.Remark = remark; 
     this.DateTime = dateTime; 
     _millilitre = millilitre; 
    } 

    public string Remark { get; set; } 
    public DateTime DateTime { get; set; } 
    public Millilitre Millilitre { get { return _millilitre; } } 
} 

雖然這將工作:

public class InsulineInjection 
{ 
    protected InsulineInjection() 
    { 
     // works with many OR/Ms 
    } 

    public InsulineInjection(Millilitre millilitre, DateTime dateTime, string remark) 
    { 
     this.Remark = remark; 
     this.DateTime = dateTime; 
     this.Millilitre = millilitre; 
    } 

    public string Remark { get; private set; } 
    public DateTime DateTime { get; private set; } 
    public Millilitre Millilitre { get; private set; } 
} 
+0

謝謝,我不知道最後一個例子可以與OR/M一起工作。 – Sardaukar

2

並非所有的.NET ORM都需要公共屬性訪問才能寫入數據。 NHibernate支持將數據寫入專用字段或設置器。但是,您需要遵循允許的字段之一,以便可以從屬性名稱中推導出字段名稱。

Check out NHibernate documentation about property mapping,特別看看錶格5.1。訪問策略和表5.2。命名策略。查看nosetter訪問策略並選擇符合您的編碼風格的命名策略。

2

爲了避免構造正在使用自己的代碼,你可以使用Obsolete attribute

[Obsolete("Default constructor only here for the ORM", true)] 
public InsulineInjection() {} 

傳遞true的屬性將產生編譯錯誤,如果你實際調用此構造函數。

+0

您還需要讓setter用於ORM,這就是他不想公開的內容。 – Servy

+0

查看該問題的其他解答 – jeroenh

+0

當您發佈問題的答案時,您應該*回答問題*,而不要依賴其他答案來真正回答問題。如果你只是想添加一些現有的答案,那麼你應該對這些答案之一發表評論。 – Servy

0

這種情況是由dapper-dot-net原生處理的。

您只需要查詢字段的順序和類型以匹配構造函數參數的順序和類型。因此,對於你的類查詢會是這樣的:

select millilitre, 
    ,dateTime 
    ,remark 
from injections 

不幸的是短小精悍怎麼會不知道的東西從十進制轉換毫升。

相關問題