7

我之前提出過這個問題,但仍然在努力尋找一個能讓我頭腦發熱的例子(請不要只是告訴我看看沒有至少某些方向的S#arp Architecture項目)。如何在不依賴NHibernate的情況下實現每個請求的NHibernate會話?

到目前爲止,我已經在我的web項目中實現了近乎持久的無知。我的倉庫類(在我的數據項目)取一個ISession構造函數:

public class ProductRepository : IProductRepository 
{ 
    private ISession _session; 
    public ProductRepository(ISession session) { 
     _session = session; 
    } 

在我的Global.asax我揭露當前會話和正在創建和的BeginRequest和endrequest配置會話(這是我有NHibernate的依賴):

public static ISessionFactory SessionFactory = CreateSessionFactory(); 

    private static ISessionFactory CreateSessionFactory() { 
     return new Configuration() 
      .Configure() 
      .BuildSessionFactory(); 
    } 

    protected MvcApplication() { 
     BeginRequest += delegate { 
      CurrentSessionContext.Bind(SessionFactory.OpenSession()); 
     }; 
     EndRequest += delegate { 
      CurrentSessionContext.Unbind(SessionFactory).Dispose(); 
     }; 
    } 

最後我StructureMap註冊表:

public AppRegistry() { 
     For<ISession>().TheDefault 
      .Is.ConstructedBy(x => MvcApplication.SessionFactory.GetCurrentSession()); 

     For<IProductRepository>().Use<ProductRepository>(); 
    } 

這似乎是我需要的ISession和我自己的通用實現ISessionFactory,我可以在我的web項目中使用並注入我的存儲庫?

所以只是爲了澄清 - 我在我的存儲庫層中使用NHibernate並希望使用會話 - 每 - (http)請求。因此,我正在將ISession注入到我的存儲庫構造函數中(使用結構圖)。目前爲了創建和處理每個請求中的會話,我必須從我的web項目中引用NHibernate。這是我想刪除的依賴項。

感謝, 本

+6

NHibernate根據我不是一個壞的依賴。 – 2010-05-26 12:43:17

+0

我的web項目與存儲庫進行通信,NHibernate是存儲庫的依賴項。如果不是因爲我希望session-per-request的事實,那麼我可以在資源庫層中打開我的會話。但是,我確實希望session-per-request,但我不希望我的web項目綁定到NHibernate。 – 2010-05-26 13:25:29

+2

Will Marcouiller:這仍然是一個依賴。依賴關係是依賴關係。如果Ben想將他的應用移植到CouchDB或MongoDB或使用內存中的對象數據庫呢? – 2010-05-26 14:22:18

回答

3

你爲什麼不創建一個IHttpModule的,並執行創建和配置有(可能在Begin_Request和END_REQUEST事件),而是把你的IHttpModule有你的NHibernate的依賴裏面的項目。例如。

namespace MyWebApp.Repository.NHibernateImpl 
{ 
    public class NHibernateModule : IHttpModule 
    { 
     public void Init(HttpApplication context) 
     { 
      context.BeginRequest += new EventHandler(Context_BeginRequest); 
      context.EndRequest += new EventHandler(Context_EndRequest); 
     } 

     private void Context_BeginRequest(object sender, EventArgs e) 
     { 
      // Create your ISession 
     } 

     private void Context_EndRequest(object sender, EventArgs e) 
     { 
      // Close/Dispose your ISession 
     } 

     public void Dispose() 
     { 
      // Perhaps dispose of your ISessionFactory here 
     } 
    } 
} 

也許有更好的辦法,我很想知道這個,所以還有其他建議嗎?

+0

找到這是我開始走下去的路線,但像你我有興趣如果有是一個更好的(更好的DI)友好的方式。 – 2010-05-26 14:40:59

+0

@Ben - 但它不是一個壞的依賴關係,因爲你不必從你的這個對象中引用它,也不會在你的web項目中引用它。你所要做的就是在你的web.config中配置它。有什麼問題?如果你通過XML配置你的DI容器,你也必須輸入它。 – jfneis 2010-05-26 19:13:28

+0

@jfneis - 你有一個使用HttpModule的完整示例 - 我特別感興趣的是如何仍然可以將我的會話注入到存儲庫以及是否以不同的方式處理事務。 – 2010-05-27 09:31:28

0

感謝大家的幫助。有一點研究讓我轉向了NHibernate Burrow項目。

從項目FAQ(http://nhforge.org/wikis/burrow/faq.aspx):

伯羅是開發,以支持使用NHibernate(也許也是本文中稱爲NH)作爲ORM框架.Net應用的輕重量的中間件。在NHibernate中使用Asp.net可能是一個挑戰,因爲NHibernate是一個有狀態的環境,而Asp.net是一個無狀態的框架。 Burrow可以通過提供先進的智能會話/事務管理和其他便利來幫助解決衝突。

我不得不跳過一些箍來讓它在我的項目中工作。由於當前版本使用舊版本的NHibernate,因此我必須從trunk中下載latest source,在VS中打開,添加對最新版NHibernate的引用並重新編譯(幸運的是沒有錯誤)。

我以多種方式測試了NHibernate Burrow。

1)繼續注射的Isession進入我的倉庫

要做到這一點,我不得不引用添加到NHibernate的,NHibernate.Burrow和NHibernate.Burrow。WebUtil到我的MVC項目。

在web.config中,我不得不建立伯羅(見http://nhforge.org/wikis/burrow/get-started.aspx),然後在我的StructureMap註冊表中添加下列內容:

 For<ISession>() 
      .TheDefault.Is 
      .ConstructedBy(x => new NHibernate.Burrow.BurrowFramework().GetSession());   

我喜歡這種方法,因爲這意味着我的倉庫(或控制器)不再加上Burrow。我不太喜歡這個事實,即我必須在我的web項目中引用這三個程序集,但至少我失去了管理會話的代碼 - 這全部由Burrow處理。

2)第二種方法是設置在的Isession我的倉庫構造像這樣:

public ProductRepository() : 
     this(new BurrowFramework().GetSession()) { } 

    public ProductRepository(ISession session) { 
     _session = session; 
    } 

我仍然可以覆蓋的Isession使我的資料庫測試。然後我對Burrow有一個直接的依賴,但也許這不是一件壞事?

另一方面,我需要從我的web項目引用的唯一程序集是NHibernate.Burrow.WebUtils。

有興趣看看兩個人中哪一個會去,爲什麼。

2

在我看來,你應該擁抱ISession並直接使用它。許多session-per-request實現的問題是它們延遲提交數據庫更改直到HTTP請求結束。如果事務失敗,那麼您在此時所能做的就是將用戶指向一個通用的錯誤頁面。管理頁面上的事務好得多,以便更有效地捕捉和處理錯誤。如果你採用這條路線,那麼你需要訪問ISession或一個包裝來控制事務。

此外,在某些時候,您的應用程序可能需要使用由ISession公開的屬性或方法,特別是Merge和Load。

+0

你會建議什麼,而不是每個請求模式的會話?或者你是否建議不要在請求中打開會話和事務,然後在請求結束時關閉它們? – RandomWebGuy 2011-09-22 22:30:10

相關問題