0

我在工作中討論聚合根和使用導航屬性來遍歷子對象。MVC DDD EF Complex子對象遍歷

方案1:

  • 客戶是聚合根
  • 地址是一個實體
  • 聯繫是

一個客戶可以有多個地址的實體和地址可以有多個聯繫人。我使用客戶ID在下面查詢客戶存儲庫並返回一個客戶對象。

Dim customer as Customer = _customerRepository.GetById(request.Id) 

如果我們需要訪問客戶地址,然後遍歷客戶對象內的地址,如下所示。

Dim address as Address = customer.RetrieveAddress(request.AddressId) 

然後,這種方法將對x個子對象進行。我已經展示了一個簡單的例子,但是對於包含數百萬條記錄的數據庫表而言,一旦聚合根對象被排隊並返回時,其他人如何在遍歷多個子對象時管理其性能問題?

方案2:

同上,但不是查詢客戶資料庫,並返回一個客戶對象的例子中,我們返回一個子對象,而不是。

Dim address as Address = _customerRepository.GetAddressById(request.AddressId) 

現在,因爲我們查詢了地址對象,這意味着我不必遍歷客戶對象才能到達它。即使我已經使用客戶存儲庫直接查詢地址表並返回地址對象,這是否允許遵循DDD?或者我應該使用方案1,在此查詢客戶存儲庫並返回作爲聚合根的客戶對象並遍歷子對象?

我問的原因是因爲在我們的DB圖中,我們有幾個表從我們的聚合根中遍歷,並且可能會隨着時間的推移而包含數百萬條記錄,這會降低性能。

只是想知道其他人如何在不降低性能的情況下徹底地應用DDD,因爲只要您使用EF時使用了導航屬性,它就會爲每個子對象發送一個查詢,如果它是在for循環中。

邁克

回答

1

聚合是一項棘手的業務,決定聚合邊界需要很多思考。閱讀你的問題我不確定你是基於行爲而不是數據庫實體關係設計你的聚合。正如Eben所說,你不會用後一種方法走得很遠,你的聚合可能最終會變得相當龐大(就兒童實體的數量而言)。

我在這個主題上讀到的最有洞察力的事情之一是Effective Aggregate Design by Vaughn Vernon。我肯定會推薦給它閱讀。他談到的一件重要事情是試圖讓你的總量儘可能小。這對性能自然有幫助。

對於孩子實體我不會做你在場景2中所做的事情,因爲如果沒有通過聚合根進行實驗,你就不應該改變實體的狀態;這保持了不變量。話雖如此,您的示例使用的地址對象很可能是值對象,因此出於性能原因使用單獨的地址存儲將會很好。

從DDD開始,我認爲重要的是要提醒您,您仍然需要務實的設計選擇; DDD並不能解決您的所有問題。在大多數情況下,設計選擇是諸如性能之類的交換。

1

你將不能夠走得很遠用ER圖來確定聚集:)

所有權不一定推斷聚集。你只是指關係遍歷。綜合根是一項棘手的業務。我曾經在博客這個有點在我的網站,你可能想看看這個特別:

Natural vs. Synthetic Aggregates

一個聚集有明顯的邊界,需要特定領域知識來判斷他的邊界。之後就是簡單地變成所有權或一個弱點。