2013-10-16 86 views
4

我理解聚合根的概念,我知道一個聚合根必須通過標識引用另一個(http://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_2.pdf),所以我不知道如何強制實體框架添加外鍵約束兩個總計之間?聚合根之間的外鍵

讓我們假設我有一個簡單的域名:

public class AggregateOne{ 
    [Key] 
    public Guid AggregateOneID{ get; private set;} 
    public Guid AggregateTwoFK{get; private set;} 
    /*Other Properties and methods*/ 
} 

public class AggregateTwo{ 
    [Key] 
    public Guid AggregateTwoID{get; private set;} 
    /*Other Properties and methods*/ 
} 

與此域的設計,實體框架不知道有AggregateOne和AggregateTwo之間的關係,因此沒有在生成的數據庫的外鍵。

+0

我的問題是你是否真的需要關心你的ORM怎麼想?:) ---的關係很可能將無論如何都要由您的數據存儲強制執行。 –

+0

由於我使用CodeFirst,數據庫將根據我的域類自動生成 –

+0

啊,我明白了。那麼,*這可能是一個問題。無可否認,我避開了ORMs,所以我不是所有的入門和出版社,但我聽說過這個代碼的第一件事:) ---我想你將無法建立參照完整性從代碼優先,因爲你不會建立關係。在創建數據庫之後,您可能需要定義參照完整性;除非有人知道一些漂亮的EF技巧。 –

回答

6

在DDD中,EF不存在。域關係與數據庫關係不同。不要嘗試將EF與域建模混合,它們不能一起工作。所以簡而言之,你有什麼沒有DDD,只是簡單的舊的關係數據庫僞裝成DDD。 EF將被存儲庫使用,並且會關注持續存在的一個聚合根(AR)。

兩個AR可以一起工作,但是您需要根據域對流程建模。 EF在那裏充當應用程序的數據庫,它關注持久性問題,不應該關心域。持久性是關於存儲的,而不是關於反映域的關係(EF實體不是域實體,儘管它們可以具有相同的名稱並且看起來相似,重要的細節是兩者屬於不同的層並處理不同的問題)。域存儲庫只關心堅持AR的方式,當它改變時可以很容易地恢復。如果更多的AR需要堅持到一起,擁抱最終的一致性,並學習如何使用服務巴士和傳奇故事。這將大大簡化您的生活(將其視爲工作單元模式的一種實現方式)。

對於查詢,最乾淨優雅的方式是生成/更新適合查詢用例的讀取模型,這通常在域事件告訴「世界」域中發生了某些變化後進行。

做DDD的權利並不簡單,它很容易陷入陷阱,相信你應用DDD的時候,實際上你只是用CRD去掉術語。如果您喜歡輕鬆的生活,那麼IMO CQRS也是DDD的必備選擇。

瞭解域名時不要急於求成和膚淺,識別有界的上下文,對域概念及其用例進行建模(非常重要!!!),根據需要定義存儲庫接口,並且只有在存在沒有別的事情可做(真正的回購,同時你可以使用像內存回收這樣的假貨 - 它們實現起來非常快,你的應用程序被分離開來意味着它不應該關心持久性是如何實現的,對嗎? )。我知道這聽起來很奇怪,但你知道你有一個可維護的DDD應用程序。

實現存儲庫的最後一點是將應用程序與持久性細節真正分開,並定義應用程序具有持久性的期望(存儲庫方法)。一旦定義,您可以編寫測試:D然後實施存儲庫。獎金是,你只關注回購實施是隔離的,當所有測試都通過時,你知道所有事情都應該如此。

+0

然後,你建議我需要維護兩個模型,一個用於我的域,一個用於實體框架?我有點困惑,因爲我讀了朱莉·勒曼文章(http://msdn.microsoft.com/en-us/magazine/ee532098.aspx?sdmr=JulieLerman&sdmi=authors),我還以爲我只需要一個模型。 –

+1

就我個人而言,當我嘗試使用EF執行DDD時,我所做的就是將ORM用於僅CRUD操作,並確保我的存儲庫都接受和返回域實體。這樣就切斷了ORM的許多好處,如果你使用Code First,可能意味着你有很多額外的工作來維護兩組實體。可悲的是,我正在開發一個項目,在該項目中我們在域中使用EF實體,但它不起作用。一旦RDBMS的細節開始泄露到您的域中,您最終會屈從於ORM,因爲它不會執行您所需的操作。 –

+0

YE 2模型,因爲每個模型都有不同的上下文。當然,從EF團隊閱讀文章告訴你,你只需要EF,但這是錯誤的。他們試圖推出一款產品,他們會喜歡你的應用與EF緊密結合。他們不關心你的應用程序的設計和可維護性。 EF是一個持久性細節,保持在那裏。 – MikeSW

0

爲什麼你應該有兩個完全不同的對象?爲什麼不僅通過域接口將您的實體暴露爲域對象? 在這種情況下,讓您的實體也可以充當域對象,並將其實現細節整齊地隱藏在界面後面,這沒有任何問題。

另一點是用EF表示聚合根的整潔方式是確保外鍵列也構成依賴實體的主鍵。在你的情況下,這意味着AggregateOneId和AggregateTwoFk一起將形成AggregateOne的組合主鍵。這將確保EF不需要用於刪除AggregateOne實例的存儲庫,只要從AggregateTwo的集合中刪除它,它就會被正確標記爲從數據庫中刪除(如果您沒有這樣的密鑰,則需要將其從AggregateOne集,因爲EF會拋出一個異常,不理解是AggregateOne應刪除開發者的意圖。