上次的 NHibernate的Session管理策略和NHibernateHelper 發布並提供下載,給NHibernate剛入門的同學們帶來很多便利。
最近有同學在求NH的通用倉儲,正好我最近也設計了一個應用於實戰,好吧,無私地分享並快樂着吧。
與上次一樣,您無需關心細節,因為我會在最后提供源代碼的下載。
如果您對ORM沒興趣,為不浪費您寶貴的時間,請點又上角紅叉。
Repository設計
從整體上可以看到,這個倉儲用到了泛型,並且繼承了一個叫BaseRepository。
BaseRepository的作用就是為倉儲提供一個特定的Session上下文,以便倉儲中使用和執行事務。
你會看到這個倉儲除了有普通的增刪改的行為以外,還提供了一系列的查詢,
這是為了在具體倉儲中可以少寫一些代碼,另外這些行為都比較細,是為了在業務層重新組裝成業務組件來使用,比如分頁組件。
在BaseRepository中就使用到了上一篇中的Session管理策略。
分頁組件
分頁組件的實現非常簡單,因為前面倉儲已經做好了鋪墊,明確地說,這個分頁組件不在倉儲,而是組織倉儲功能。
因為作者認為有些分頁需要返回一個總記錄數,這個其實是特定的分頁插件需要考慮的,而倉儲不應該知道UI插件的存在而專門為一個UI插件提供功能。
你會發現GetCount函數並沒有白白准備,而實戰中關聯對象的List<T>.Count可能會做一次延遲加載的查詢,所以這個函數必不可少。
可使用Query對象,也可直接使用HQL。
分頁的實戰
注意:對於復雜的查詢建議不要太考慮分層,就算留點灰色空間吧。因為多實體關聯考慮到自定義的別名(比如from obj1 as o1 left join o1.XXX as o2 where o2.XXX=XXX),如果別名由業務層或更高層指定的話,相當於高層類庫需要了解低層類庫中HQL的結構了,這種情況分層不如不分。
另外簡單的分頁條件查詢可以使用如下示例。
條件查詢
排序
事務管理和Repository的重用考慮
我們通常會在領域模型Service中組織倉儲,供更上層的調用,而在倉儲中控制事務的打開和提交,明顯會阻礙倉儲在業務層被重用。
解決的思路可以看我的業務邏輯層設計——事務的考慮,下面我給出一個簡單的做法。
這里使用BaseService自己封裝的事務控制。
Session.SaveOrUpdate()也可以調用倉儲的Update()代替,比如:new PurchaseOrderRepository().Update();
花絮
這個項目本來是基於.NET2.0的,所以我並沒有打算給他升級,所以NH版本選擇了2.1,也就沒有Linq, 也就沒有fluent。
參考過很多書籍和博客
感謝博客園前輩們
李永京、弦哥、劉冬.NET、博客園NHibernate專題。
參考書籍
《Microsoft .NET企業級應用架構設計》
《領域驅動設計》
附件下載