8

我正在爲我的應用程序使用實體框架4.1和ASP.Net MVC 3。 MVC提供了表示層,一箇中間庫提供了業務邏輯和實體框架類的行爲作爲我猜想的數據層?實體框架,應用程序層和關注點分離

我可以將實體框架代碼分成一組存儲庫類或其適當的變體,無論構成一個有價值的數據層,但是我在解決設計問題時遇到了問題。

如果存在多層方法來幫助我關注問題,那麼我認爲我選擇的數據持久性也不應該成爲表示層的問題。問題是,通過使用實體框架,我基本上緊密地將我的應用程序與實體更改自動跟蹤並保持的概念緊密耦合。

因此,讓我們假設在一個假設的世界中,我找到了一個不使用實體框架的理由,並希望將其交換出去。一個設計良好的解決方案應該允許我在適當的層執行此操作,而不會影響依賴層,但是因爲所有代碼都是在知道數據層跟蹤對象更改的情況下編寫的,所以我只能將實體以類似的方式工作的框架,例如nHibernate。

如何使用實體框架但不需要以假定實體更改正在被數據層跟蹤的方式編寫我的代碼?

更新那些仍然不知道這個問題在他們自己的情況:
Ayende Rahien寫了一大篇擊落這整個論點: http://ayende.com/blog/4567/the-false-myth-of-encapsulating-data-access-in-the-dal

回答

9

如果你想繼續這種方式,你應該放棄的編程工作,去學習哲學。實體框架是對持久性的抽象,並且存在一條規則Leaky abstraction,其規定任何不平凡的抽象在某種程度上是泄漏的。

敏捷方法帶有一個非常有趣的現象:不要爲假設情況做準備。大部分時間只是Gold plating。每個變化都有其成本。在項目後期更改持久層代價很高,但也非常少見。從客戶角度來看,沒有理由在大多數不需要此項變更的項目中支付部分成本。如果我們更深入地討論客戶的觀點,我們可以說他不應該爲此付出代價,因爲選擇後來必須替換的糟糕API是開發人員/架構師的失敗。定期重構您的代碼,但僅限於添加客戶需要的新功能所需的點,否則您很難在市場上具有競爭力。這當然有一些例外:

  • 客戶希望(或架構要求它出於任何原因,客戶同意)這樣的抽象。在這種情況下,您必須指望它,併爲此類更改定義架構。
  • 它是愛好或開源項目在這裏你可以做你想做的,因爲它不是由某些資源

現在你的問題的制約。如果你想要這樣高層次的抽象,你不應該將實體暴露給你的控制器。從業務層(甚至是存儲庫)公開DTO,並向這些DTO添加IsNew,IsModified,IsDeleted等字段。現在您的用戶界面與持久性完全分離,但您的架構要複雜得多,並且可能沒有理由產生這種複雜性 - 它已經過時了。另一種方法可以簡單地關閉跟蹤(爲每個查詢添加AsNoTracking())並在您的實體上創建代理(context.Configuration.ProxyCreationEnabled) - 延遲加載也不會起作用。這就像扔掉大部分功能持久性框架提供給你的。

還有其他觀點。我建議您閱讀Ayende's最近關於存儲庫和他對夏普體系結構的評論。

+1

只是想補充一點,所有的ORM也會分擔一些難以替換的差異。 關閉我頭腦中的差異包括級聯刪除行爲,急切的加載行爲,linq行爲(必須在跳過之前執行命令),存儲過程/視圖行爲,臨時sql行爲,投影行爲,甚至與LINQ。神話可交換的ORM層不存在。無論如何,你需要做很多工作。 – jfar 2011-05-11 21:10:04

+0

很好的答案!老實說,有時候我只是需要將這些東西從別人身上反彈出來,讓我放心。 – 2011-05-12 10:26:53

+0

對於單個應用程序來說,這是一個很好的觀點,但是如果您計劃編寫多個應用程序並且它們都應該使用相同的基本概念(也許還有代碼庫),那該怎麼辦?然後事情變得複雜,你不能只是「建立客戶想要的」(他不知道)。 – Marc 2017-07-06 11:40:18

0

你應該實現,如果你的倉庫模式和普通POCOS擔心可能會更換EF。

在Codeplex上有一個很好的項目,它覆蓋了域驅動設計,包括文檔。看看那個。

http://microsoftnlayerapp.codeplex.com/

+0

在我看來,這是擊敗持久性無知的目的。我的控制器層不應該關心我是使用ORM還是存儲庫模型。 – 2011-05-11 18:53:15

+0

如果這兩件事不提供相同的功能,那麼你的控制器層肯定應該關心。某些自動跟蹤和保持更改需要根本不同的控制器邏輯。 – Tridus 2011-05-11 21:37:29

+0

你是對的,正如我所說的,你可以使用普通的POCOS並將它們作爲DTO傳遞 - 它們應該是持續的無知。存儲庫模式不會讓鴿子使用任何特定的數據訪問方法。 – 2011-05-13 00:14:44

2

簡答題?你沒有。您可以關閉EF的跟蹤,然後不用擔心,但就是這樣。

如果您打算編寫您的表示層,並期望自動跟蹤並保持更改,那麼無論您替換EF都必須這樣做。您不能將它交換出來,因爲它不會自動跟蹤並保持更改,只是希望事情能夠繼續工作。這就像一個依賴TCP/IP連接進行雙工通信的系統,將它交換到一個HTTP連接(HTTP的本質並不是真正的雙工),並希望事物以同樣的方式工作。它沒有。

如果您希望能夠將持久層換成別的東西而不必更改其他任何東西,那麼您需要在自己的自定義代碼中包裝EF(或其他),以提供所需的功能。那麼你必須提供任何不是由你交換的東西提供的實現。

這是可行的,但對於實際上很少發生的問題,這將是一項可怕的工作。這也會增加項目的複雜性。拉迪斯拉夫喋喋不休:這不值得抽象。

0

請在閱讀微軟n層項目之後,閱讀ayenede's weblog. Mr.ayende發佈了關於微軟n層項目優勢和劣勢的系列文章。

相關問題