儲存庫模式 - 如何正確處理 JOIN 和復雜查詢?
我對儲存庫模式有疑問 - 如何在多個儲存庫之間執行 JOIN 操作。在這個項目中,我們使用 MVC、EF、DDD。我知道這種問題在這裡多次出現,我稍後會在本文中提到這些問題。
在通用儲存庫模型(IRepository)和特定儲存庫模型之間,我選擇了特定選項,因為我認為 ORM(在我們的例子中為 EF)本身就是通用儲存庫模式,因此添加另一個通用儲存庫沒有意義,我們會而是根據域需求定制儲存庫。
問題是我有幾個(約 10 個)表,每個表都有很多行(數百萬),我需要執行 JOIN,所以使用 IList 或 IEnumerable 是不可行的選擇。
我的理解(和我的觀點)是 IQueryable 不應該離開儲存庫(“在 DAL 中發生的事情應該留在 DAL 中。”)。公開 IQueryable 並在服務中的 LINQ 中使用它會更簡單,但它強烈違反關注點分離並破壞儲存庫的作用——在這種情況下,服務將做與儲存庫相同的事情。舉幾個例子,這些文章支持這個觀點(或者更確切地說是信念):
返回 IQueryable<T> 或不返回 IQueryable<T>
我應該從我的 DAL 返回 IEnumerable<T> 還是 IQueryable<T>?
<http://www.shawnmclean.com/blog/2011/06/iqueryable-vs-ienumerable-in-the-repository-pattern/>
<http://blog.ploeh.dk/2012/03/26/IQueryableTisTightCoupling/>
也有類似的問題和解決方案,例如How to join Multiple tables using Repository Pattern & Entity Framework? 建議使用 .Include(),但這不是用於重載表和跨多個表連接的選項 - 對於每個 JOIN,我們使用子選擇來限制實際連接的內容)。
這個問題(答案和評論) -如何使用儲存庫模式查詢交叉表?- 基本上建議基於任務的差異化:為使用 JOINS 的查詢創建一個儲存庫,並為每個實體的操作創建“正常”儲存庫。
我看到我們有以下選擇:
- 暴露 IQueryable 並在服務中執行 JOIN 複雜查詢;我真誠地覺得這是反模式,我不喜歡那樣。
- 不要對這 10 個表使用 Repository 並在服務中執行查詢;一些文章建議使用 EF 就足夠了(例如,是否可以繞過儲存庫模式進行複雜查詢?),我不同意這一點。
- 使用基於任務的差異化,不要限制儲存庫 1:1 repo:entity(我贊成這個選項)
- 完全不同的東西?
那麼 - 你有什麼建議?一次又一次,謝謝你。
- 意味著將持久性洩漏到應用程序中——反模式、意大利麵條程式碼。
- 它與(1)有何不同?還是同樣的問題。
- 近一點……
- 使用查詢對像模式。將您的複雜查詢封裝在與儲存庫一起駐留的基於任務的對像中。它可以返回針對視圖而不是域對象優化的 DTO。
- 嚴重依賴 QO 將導致您使用稱為 CQRS -命令-查詢責任分離的架構。
還有一件事。entity:repo 沒有 1:1 匹配。只有聚合應該有一個儲存庫,而不是每個實體。