14

那麼,不知道這是否正確的標題,但基本上我已經有很多問題在MVC應用程序中使用存儲庫,以便您可以替換一組存儲庫,實施另一種不同的數據存儲技術。使用存儲庫模式來支持多個提供商

例如,假設我想爲我的應用程序使用實體框架。不過,我也希望在硬編碼列表中實現一組測試數據。我想要有一組接口(IUserRepository,IProductRepository等 - 我們現在不要談論更通用的IRepository <T>),這兩種方法都可以實例化。然後,使用(比如說)一個依賴注入工具,比如Ninject或Castle Windsor,我可以在實體框架提供者(訪問實際數據庫)和測試提供者(訪問列表)之間來回切換。

概括地說,這裏的問題:

- 如果你要使用實體框架,你希望你的倉庫返回的IQueryable <SOMETYPE>。

- 如果您打算使用硬編碼列表,您不希望您的存儲庫返回IQueryable,因爲它會大大增加開銷,而且,Linq to Entities與Linq to Objects顯着不同,導致很多代碼頭痛,這是兩個提供商共同的。

換句話說,我發現最好的方法是隔離存儲庫中所有依賴於EF的代碼,這樣這些存儲庫本身就會返回IEnumerable或IList或其他類型的 - 然後EF和其他一些技術都可以使用相同的存儲庫。因此,所有的IQueryable將被包含在EF倉庫中。這樣,您可以將EFL存儲庫中的Linq to Entities和測試存儲庫中的Linq用於對象。

然而,這種方法將大量的業務邏輯放入存儲庫,並導致代碼重複得很多 - 即使實現有所不同,邏輯也必須在每個存儲庫中重複使用。

因爲這個非常薄的層僅僅連接到數據庫,所以存儲庫的全部概念就會丟失 - 存儲庫就是業務邏輯和數據存儲連接的「存儲庫」。你不能只是有查找,保存,更新等。

我一直無法解決需要隔離提供程序相關的代碼,並在一個集中的位置業務邏輯之間的這種差異。

任何想法?如果任何人都可以指點我一個解決這個問題的實施例子,我會非常感激。 (我已經讀了很多,但無法找到任何具體談這些問題。)

UPDATE:

我想我開始覺得這可能不是可能有倉庫,可以換成不同的提供者 - 例如,如果你打算使用實體框架,你只需將整個應用程序投入實體框架。單元測試?我正在爲此苦苦掙扎。我現在的做法是建立一個包含硬編碼數據的單獨存儲庫,並將其用於單元測試,並在數據庫建立之前測試應用程序本身。我想我將不得不尋找一個不同的解決方案,或許是一些嘲弄的工具。

但是這就引發了爲什麼要使用存儲庫的問題,特別是爲什麼要使用存儲庫接口。我正在研究這個。我認爲確定最佳實踐需要進行一些研究。

+0

關於IQueryable的另一篇文章:http:// stackoverflow。簡而言之,這總結了我認爲每個人都會遇到的狀態以及他們在學習時在線上某些點上所具有的問題.net .net/com/questions/718624/to-return-iqueryablet-or-not-return-iqueryablet – aqwert 2011-05-18 21:40:52

+0

/mvc/ef /設計模式。有用的問題和答案 – 2012-12-05 11:29:56

回答

14

我能說什麼?歡迎來到俱樂部......

你發現的問題是很多開發者在EFv4中追隨「資源庫繁榮」時遇到的問題。是的,這是問題,問題非常複雜。我討論了好幾次:

獨立的主題就是爲什麼要使用庫:

基本上你提出的方法是解決方案,但你真的想要它嗎?在我看來,結果不是存儲庫,而是數據訪問對象(DAO)暴露了大量的訪問方法。通過Martin Fowler存儲庫定義是:

阿庫介導 域和數據映射層之間,作用 像一個內存域對象 集合。客戶對象以聲明方式構造 查詢規範,並將 提交給Repository,以獲得 滿意度。對象可以被添加到 併除去從所述存儲庫,因爲 它們可以從 對象的簡單集合,並且由存儲庫封裝映射代碼 將 進行適當的操作 幕後。從概念上講,存儲庫封裝了持久存儲在數據存儲中的對象集合 和通過它們執行的操作, 提供了持久層的更加面向對象的視圖 。存儲庫 也支持 的目標實現域 和數據映射層之間的乾淨分離和 單向依賴性。

我相信暴露IQueryable符合然後創建類似於從存儲過程的時代倉庫公共接口更好的這個100倍 - 在每個存儲過程(固定查詢)一個訪問方法。

該問題可以通過leaky abstraction的規則來總結。 IQueryable是數據庫查詢的抽象,但IQueryable提供的功能依賴於提供者。不同的提供商=不同的功能集。

什麼是結論?你是否因爲測試需要這樣的架構?在這種情況下,開始使用前兩個鏈接答案中提出的集成測試,因爲在我看來這是最可怕的方式。如果你採用你提出的方法,你仍然應該使用集成測試來驗證你的倉庫隱藏所有EF相關的邏輯和查詢。

+0

哇,很多閱讀!讓我反思一切,明天我會回到你身邊。 – Cynthia 2011-05-18 23:05:00

+0

我是通過你的例子的一部分。我對你的陳述有一個問題:「第一個原因是某種建築的純粹性和好主意,如果你讓你的上層獨立於EF,你可以在以後轉換到其他持久性框架。你看到過多少次現實世界中的東西?「其實我幾年前不得不這樣做,我的第一個MVC項目。我首先使用了EF代碼,但是在我需要它之前,我認識到它不會是RTM,所以我必須在時間壓力下切換到強類型數據集。 (續...) – Cynthia 2011-05-18 23:18:42

+0

我不得不創建一個新的存儲庫,並且我不得不更改所有存儲庫接口,以便返回IEnumerable而不是IQueryable,並且發誓我永遠不會再陷入這種情況。現在EF 4.1已經不存在了,但這個經歷已經深入到我的大腦之中 - 儘管我明白了你的觀點,但我真的不喜歡這個存儲庫依賴於特定技術的想法。更多後來... – Cynthia 2011-05-18 23:21:44