2011-11-29 81 views
1

過去幾天我一直在閱讀關於實體框架的知識,並設法使用它,但我仍然有幾個問題,其中一些問題可能看起來有點太基礎。爲了透視,我在asp.net web應用程序中使用實體框架4.0。如果您可以回答任何問題,請繼續。實體框架(有關POCO,上下文和DTO的問題)

  1. 通過使用POCO模板我有什麼優勢。我明白,如果我希望得到持久性的無知,並讓我的實體清除與存儲有關的任何信息,POCO實體是要走的路。另外,我可以從實體框架切換到使用POCO實體時相對容易的NHibernate?除了鬆散的耦合之外,我還有什麼重要的理由要走向POCO實體。另外如果我確實使用POCO,我最終會失去什麼。在代理的幫助下,我還能獲得更改跟蹤和延遲加載嗎?

  2. 使用EF模型的實體作爲數據傳輸對象或業務對象是正常實踐嗎?即例如我爲我的實體模型有一個單獨的類庫。假設我正在使用MVP,我想在公司中列出員工列表。演示者將請求我的業務邏輯功能,該功能將查詢實體模型中的員工列表並將實體列表返回給演示者。在這種情況下,我的演示者需要參考EF模型。這是正確的方法嗎?在我的asp.net網絡應用的情況下,它不應該成爲一個問題,但如果我使用的是Web服務,它是如何工作的?這是去POCO實體的理由嗎?

  3. 假設員工實體具有公司表的導航屬性。如果我在「使用」塊中使用和包裝數據上下文,並嘗試訪問BL中的導航屬性,我假設我會得到一個異常。如果關閉延遲加載並使用「包含」linq查詢來獲取實體,我是否也會遇到異常?在之前的帖子中,有人建議我使用每個請求的上下文,這意味着即使當我在BL中時,上下文仍保持活動狀態。如果我希望堅持我所做的任何更改,我假設我仍然需要分離該對象並將其附加到我的下一個請求的上下文中。或者相反,我應該再次用新的上下文查詢對象並更新它?

  4. 這個問題更多的是與組織文件/最佳實踐有關,並且是我之前發佈的問題的後續。當我使用基於實體的單獨文件來組織我的數據訪問層時,組織我的查詢涉及多個表之間的連接的最佳做法是什麼。我對組織還是有點朦朧。已嘗試在線搜索,但沒有太多的幫助。

回答

5

好棒的問題。我的第一個建議是以模式思考。隨着這說...

  1. 你幾乎釘了使用POCO的優勢。將您的業務對象(PO​​CO實體)與數據訪問層分離有一些獨特優勢。但主要原因就像您所說的改變或修改以下圖層的能力。然而,使用POCO你基本上遵循了Code First(CF)方法。就我個人而言,我認爲它是並行代碼,取決於您的軟件開發生命週期。您仍然擁有數據或模型第一種方法所具有的所有功能和哨聲,因爲您可以在後臺擴展ObjectContext的DbContext。我讀了一篇文章,我似乎無法找到,CF是Entity Framework的未來。最後,POCO的好處是你可以在這裏或其他地方加入驗證規則。你也可以提供預測。假設你有出生日期,但你也想要一個年齡屬性。當映射到數據庫時Age屬性被忽略,現在變得毫不起眼。
  2. 就我個人而言,我爲大型項目創建自己的業務對象(PO​​CO),這些項目傾向於擁有自己的生活,而改變是生活方式。另一個想法是可擴展性和可維護性。如果我選擇在應用程序之間進行功能分離,就像您提到的Web服務一樣,功能現在是從兩個不同的位置提供的。如果將業務對象和DAL封裝在相同的代碼塊中,則分離或可伸縮性現在變得更復雜一些。但是,請考慮該項目。它可能很小,將來的變化很小,所以不需要投擲手榴彈來殺死蒼蠅。在哪個時間數據首先可能是要走的路,讓edmx文件代表你的對象。所以不要把自己嫁給一種技術或一種方法論/模式。做你的時間和業務是有意義的。
  3. 使用語句非常好。事實上,我最近開始將它包裝在TransactionScope中。如果發生錯誤,則回滾是固有的。接下來,需要考慮的是UnitOfWork。 UnitOfWork模式封裝了數據上下文在你工作的範圍內需要執行什麼的快照。對於每個UnitOfWork,您都有一個需要執行工作的主題。例如員工。因此,如果要保存員工信息以保持簡單,則可以調用BL服務或存儲庫(以前)。在那裏你傳入Employee Id,在UnitOfWork下執行一些工作,在構造函數中實例化它或使用依賴注入(DI或IoC)。簡單的入門者是StructureMap。那裏的服務會對你的UnitOfWork(DbContext)進行必要的調用,然後將控制返回到上游(例如UI)。
  4. 在這裏學習的最好方法是查看其他代碼。我會從一些微軟的例子開始。我會從書呆子晚宴(http://nerddinner.codeplex.com/)開始,然後建立起來。

補充閱讀:

Use prototype pattern or not

http://weblogs.asp.net/manavi/archive/2011/05/17/associations-in-ef-4-1-code-first-part-6-many-valued-associations.aspx

[編輯] NightHawk457,我非常不回答你的問題抱歉。希望你明白,但爲未來的讀者...

爲了幫助大家可視化,想象下面的架構使用領域模型和存儲庫爲例。請記住,皮膚有很多方法可以讓皮膚變成貓眼,不要忘記我上面的Grenade評論。

  • 數據層數據訪問):MyDbContext:的DbContext,IUnitOfWork,其中IUnitWork合同CRUD操作。
  • 數據存儲庫數據訪問/業務邏輯):MyDomainObjectRepository:IMyDomainObjectRepository,其接收由工廠類或依賴注入IUnitOfWork。在CRUD操作上調用MyDomainObject驗證。
  • 域模型業務邏輯):MyDomainObject使用[自定義]驗證屬性。閱讀this的優缺點。
  • MVVM/MVC/WCF演示/服務層):以往你所選擇的附加層,您現在可以訪問您的數據,該數據在更小的模塊誰是它們的功能自密封包裹的很好。表示層(例如ViewModel,Controller,Code-Behind等)可以通過Factory類或依賴注入接收IMyObjectRepository。

提示:

  • 通連接字符串到MyDbContext因此可以重用MyDbContext。
  • MySql與System.Transactions.TransactionScope,example不兼容。我不記得確切,但它是MySql不支持的東西。這使得測試有點困難,因爲我們已經創建了這種級別的分離。
  • 爲每個圖層和最小測試通用功能/規則創建一個測試項目。
  • 每個域對象應至少擴展ID域爲最小的基礎對象。也不要在這裏實現關鍵屬性。域對象不應描述體系結構,而應將特定數據描述爲實體。即使在Code First上,這也可以通過Fluent API來實現。
  • 在創建MyDbContext時思考泛型。 ;)閱讀迭戈的post
  • 在ASP.NET中,這些存儲庫很適合用於ObjectDataSources。

正如您所看到的,IUnitOfWork和IMyDomainObjectRepository是暴露上述圖層功能的接口的角色明確分離。舉例來說,IUnitOfWork可以是NHibernate,Entity Framework,LinqToSql或ADO.NET,其中對工廠類或依賴注入註冊的更改都是必須改變的。僅供參考,我聽說Repository也稱爲服務層。我個人喜歡第一個名字不要與Web服務混淆。這個結構的下一個重要目標是實現數據庫上下文(IUnitOfWork)的範圍。一個簡單的例子就是一個ASP.NET頁面,其中每個頁面都有一個且僅有一個IUnitOfWork用於每個存儲庫或用於該範圍的工作。對於ViewModels,Controllers等等也是如此。因此,假設您需要使用兩個存儲庫EmployeeRepository和HRRepository。然後您可以在兩者之間共享IUnitOfWork。爲了跨越頁面,視圖模型或控制器邊界,我們使用該ID作爲實體,然後將它們從數據庫中提取出來並執行工作。您也可以跨越邊界傳遞DTO並附加到上下文,但是隨後開始失去圖層分離。

要繼續,POCO類不必自動生成。事實上,您可以從頭開始創建實體類,並在OnModelCreating(DbModelBuilder mb)方法內的擴展DbContext類中執行映射。開始here,然後here並注意其他資源,谷歌Fluent API並閱讀迭戈這post

至於驗證,這是一個有趣的觀點,因爲如果所有業務規則都可以在一個位置進行驗證,那將是非常棒的。那麼,我們都知道這並不是很好。因此,這裏是我的建議,儘可能在數據註釋中保留所有數據級別的驗證(即必需的,範圍,格式等)在域對象中,並在存儲庫中保留明確角色的進程驗證(即如果isEmployee)做到這一點,否則)。我說得很清楚,這樣你就不想在兩個不同的存儲庫中添加一個員工,而這個存儲庫中的驗證必須重複。要調用驗證,請啓動here。捕獲ValidationResults並向上遊發送一個MyRepositoryValidationException,其中包含一組驗證錯誤(例如Employee是必需的),這些錯誤可以呈現給表示層。綜上所述,不要忘記在表示層執行驗證。例如,您不希望發佈帖子以確保員工擁有有效的電子郵件。

只記得平衡時間和努力與複雜性。對於簡單的事情,使用Data First或Model First與您的EDMX文件。然後在包含所有驗證規則的頂部放置一個存儲庫。

+0

使用POCO's不是代碼優先。您可以首先將POCO的數據庫放在數據庫中,然後模型化。 Code First僅指模型定義的方式。在Code First中,這是通過流利的映射完成的,首先在數據庫和模型中完成,這是通過.edmx文件完成的。 –

+0

謝謝傑夫 - 我正在研究UnitOfWork和RepositoryPatterns。只有經過一些閱讀後,纔有可能對3進行更好的評論。關於爲POCO類添加驗證,我假設您正在通過數據註釋討論驗證?我假設你將不得不在這裏使用部分類,因爲如果POCO類是自動生成的,如果它在同一個類中,我們將失去驗證。我也必須做一些閱讀,但如果我在這方面脫軌,你如何進行驗證? – nighthawk457

+0

感謝您糾正我Mystere人。爲了擴展你的觀點並進一步修正我自己,我們也可以使用部分類來擴展生成的對象。 –