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