我在晚上的其餘時間閱讀了StackOverflow的問題以及一些關於該主題的博客文章和鏈接。他們都變得非常有幫助,但我仍然覺得他們並沒有真正回答我的問題。靜態存儲庫是使用NHibernate的正確方法嗎?
所以,我正在開發一個簡單的Web應用程序。我想創建一個可重用的數據訪問層,以後我可以在其他解決方案中重用。其中99%是網絡應用程序。這似乎是我學習NHibernate及其周圍模式的一個很好的藉口。
我的目標如下:
- 我不想業務邏輯層瞭解數據庫的內部運作任何東西,也沒有NHibernate的本身。
- 我希望業務邏輯層儘可能少地假設數據訪問層。
- 我希望數據訪問層儘可能簡單和易於使用。這將是一個簡單的項目,所以我不想過分複雜。
- 我希望數據訪問層儘可能地不侵入。
會不會考慮到所有這些,我決定採用流行的倉庫模式。我在本網站和各種開發人員博客上閱讀了這個主題,並且聽到了有關工作單元模式的一些內容。
我也環顧四周,檢查出各種實現。 (包括FubuMVC contrib和SharpArchitecture,以及某些博客上的內容)。我發現其中大多數操作原理相同:它們創建一個「工作單元」,在存儲庫實例化時它們實例化,它們開始一個事務,做東西,然後提交,然後重新開始。所以,只有一個ISession
每Repository
就是這樣。然後,客戶端代碼需要實例化一個存儲庫,做一些事情,然後處理。
此使用模式不符合我需要的是儘可能的簡單化,所以我開始思考別的東西。
我發現NHibernate的已經擁有的東西,這使得「工作單位」不必要實現自定義,那就是CurrentSessionContext
類。如果我正確配置會話上下文,並在必要時進行清理,那麼我很好。
所以,我想出了這個:
我有一個名爲NHibernateHelper
內部靜態類。首先,它有一個名爲CurrentSessionFactory
的靜態屬性,它在第一次調用時實例化會話工廠並將其存儲在靜態字段中。 (每一個ISessionFactory
一個AppDomain
是不夠好。)然後,更重要的是,它有一個CurrentSession
靜態屬性,檢查是否有綁定到當前的會話上下文的ISession
,如果沒有,創建一個,並結合它,它返回ISession
綁定到當前會話上下文。
因爲它將被WebSessionContext
大多使用(每HttpRequest
所以,一個ISession
,儘管對於單元測試,我配置ThreadStaticSessionContext
),它應該無縫地工作。創建並綁定ISession
後,它將事件處理程序掛接到HttpContext.Current.ApplicationInstance.EndRequest
事件,該請求在請求結束後負責清理ISession
。(當然,只有做到這一點,如果它真的是在網絡環境中運行。)
所以,這一切成立,NHibernateHelper
隨時都可以返回一個有效的ISession
,所以沒有需要實例一個爲「工作單元」正確運行的Repository實例。相反,Repository
是一個靜態類,它與NHibernateHelper.CurrentSession
屬性中的ISession
一起運行,並通過泛型方法公開功能。
所以,基本上,我結束了兩個非常懶惰的單身人士。
我很好奇,你怎麼看待這個問題? 這是一種有效的思維方式,還是我完全偏離了這裏?
編輯:
我必須指出的是,NHibernateHelper類是內部的,所以幾乎看不到消費者的存儲庫。
另一個想法是,爲了引入依賴注入到解決方案中,需要創建一個名爲IDataProvider
的接口,並在第一次調用Repository
類時實例化該接口的一個實例。 (然而,實現代碼應能照顧上下文的概念也。)
編輯2:
似乎很多人都喜歡我的想法,但仍有關於它的太少意見答案。
我可以假設這是一個正確的方式來使用NHibernate,然後呢? :P
嗯是的,但我認爲我的解決方案有一個更容易使用的語法,並且在對象實例化方面以及內存使用方面肯定更少。 – Venemo 2010-04-26 22:45:54