0

我想知道如何跟隨DDD的人繞過使用EF和存儲庫模式的潛在性能問題,並返回帶有子級的聚合根。DDD存儲庫EF性能

例如父 -----孩子A

甚至例如家長 ----- Child A級 -------兒童A2

  1. 如果我從倉庫中帶回的聚合根的數據,並使用導航屬性EF然後觸發了另一個查詢,因爲它是利用懶加載。這是一個問題,因爲我們在循環中遇到100多個查詢。
  2. 如果我使用'Include'語句從存儲庫中帶回子數據的聚合根數據以及'Include'語句,這將從存儲庫帶回父節點的子數據。然後,當我使用導航屬性時,由於該數據已存在於內存中,因此沒有查詢會被觸發。

第二種方法的問題是,我們的一些孩子對象的數據可能很大,例如100,000+條記錄。 很顯然,我不想爲孩子存儲10萬條以上的記錄。我們決定一次使用分頁來選擇10來解決這個問題,但另一個問題是當我們試圖使用像sum,total count等孩子的計算,但我們只能在內存中記錄我們擁有的10條記錄拉回來。

我知道DDD的辦法就是拉回來對象圖與它的所有內存中的數據,然後您完成您需要顯示的數據對象遍歷。

我們的團隊中存在分裂,有些人認爲我們應該撤回聚合根和它們的孩子在一起,有些人認爲我們應該有一個聚合根存儲庫的方法,直接查詢兒童數據並將子對象拉回。

我只是想知道其他人如何解決大量數據與父/子存儲在內存中的性能問題。

+0

也許你必須在某些情況下重新建模/分割你的實體。此外,不要忘記,您可能必須在複雜場景中丟棄LINQ查詢,並將存儲過程映射到實體數據模型。這也可以提高性能。 – hoetz 2012-07-11 08:37:55

回答

0

如果你必須處理性能,您必須使用與暴露在倉庫特殊方法的第二種方法 - 這是倉庫的角度爲您提供這樣的方法,否則,您可以使用EF上下文/直接設置。

理論是很好的,如果你使用理論數據 - 一旦你有真實的數據,你必須調整理論在真實世界的情況下工作。

您還可以檢查this article(也有在博客上的以下三個文章)。它做了第二種方式,但它假裝成爲第一種方式。它適用於Count,但也許您可以將其用於其他一些場景。

0

DDD方式並不總是能夠回退所有需要的數據。我們使用一種稱爲雙派遣模式的技術。這是您使用所有需要的參數調用聚合根方法(或域服務)的地方,同時也是您傳遞「僅查詢」存儲庫類型接口參數的地方。這使得根或其子級能夠決定需要哪些額外數據,以及何時應該通過簡單地調用此注入接口上的方法來返回。

該方法遵循DDD原則,該原則聲明聚合根不應該意識到存儲庫的實現,同時提供可測試和高性能的域代碼。

+0

如果每個根(也可能是孩子)發起自己的查詢以獲取額外數據,這怎麼能夠「高度表現」?此外,如果這意味着域對象應該填充自己的孩子,我想知道這是否符合DDD原則。也許一個小例子可以澄清這一點。 (我不否認你的方法,這很有趣,但只是想知道一些事情)。 – 2015-01-26 08:02:28

+0

也許高性能是一個錯誤的術語 - 讓我們高度靈活;)。這種模式允許你做什麼的是當你檢索必要的數據時調整。在某些情況下,您可能需要預先加載所有數據(急切加載),並讓聚合根/子級決定何時顯式加載其他項目。 – user4492710 2015-01-26 18:40:05

+0

也許高性能是一個錯誤的術語 - 讓我們高度靈活;)。這種模式允許你做什麼是定製你何時檢索必要的數據。在某些情況下,您可能希望預先加載所有數據(急切加載),並讓聚合根/子級決定何時顯式「加載」其他項目。通常情況下,你不希望實體每次都獲取自己的數據(這將成爲維護的噩夢),但是在某些情況下,只要存儲庫實現細節沒有泄漏到實體中,它就會處於良好狀態,會敲出一個示例。 – user4492710 2015-01-26 18:51:35