2010-10-12 100 views
2

我在寫一個使用ASP.NET MVC 2的Web應用程序,並選擇NHibernate作爲我的ORM。我基本上從觀看NHibernate系列夏季課程中學習了我的基礎知識,並採用了作者會話管理會話的每個請求策略(Ep 13)。事情似乎運作良好,但我擔心這是否是管理會話和線程安全的功能性現實世界方法。如果不是,我可以接受其他例子。Web應用程序NHibernate會話管理NHibernate風格的夏天

我已經添加了代碼來詳細說明。 這裏是我的代碼,建立了一個SessionFactory:

public class NHibernateSessionManager 
{ 
    public static readonly ISessionFactory SessionFactory; 

    static NHibernateSessionManager() 
    { 
     try 
     { 
      Configuration cfg = new Configuration(); 

      if (SessionFactory != null) 
       throw new Exception("trying to init SessionFactory twice!"); 

      SessionFactory = cfg.Configure().BuildSessionFactory(); 
     } 
     catch (Exception ex) 
     { 
      Console.Error.WriteLine(ex); 
      throw new Exception("NHibernate initialization failed", ex); 
     } 
    } 
    public static ISession OpenSession() 
    { 
     return SessionFactory.OpenSession(); 
    } 
} 

而這正是我有web請求啓動和停止交易:

public class NHibernateSessionPerRequestModule : IHttpModule 
{ 
    public void Dispose() 
    { 
    } 

    public void Init(HttpApplication context) 
    { 
     context.BeginRequest +=new EventHandler(Application_BeginRequest); 
     context.EndRequest +=new EventHandler(Application_EndRequest); 
    } 

    private void Application_BeginRequest(object sender, EventArgs e) 
    { 
     ISession session = NHibernateSessionManager.OpenSession(); 
     session.BeginTransaction(); 
     CurrentSessionContext.Bind(session); 
    } 
    private void Application_EndRequest(object sender, EventArgs e) 
    { 
     ISession session = CurrentSessionContext.Unbind(NHibernateSessionManager.SessionFactory); 
     if(session != null) 
      try 
      { 
       session.Transaction.Commit(); 
      } 
      catch (Exception) 
      { 
       session.Transaction.Rollback(); 
      } 
      finally 
      { 
       session.Close(); 
      } 
    } 
} 

這是我會怎樣抓住從一個會話一個控制器類的我的倉庫中的一個會話工廠:

CompanyRepository _companyRepository = new CompanyRepository(NHibernateSessionManager.SessionFactory.GetCurrentSession()); 

回答

1

我很好奇,所以我搜索了一下。

HttpContext.Items可以被多個線程使用。

Nhibernate會話不是線程安全的。

再有就是有回答:(可重複) NHibernate thread safety with session

所以看來這後患無窮可以有效地管理。因爲你沒有發佈夏季Nhibernate用它很難說的代碼來說明你的實現是否會崩潰。

+0

所以用上面的代碼,因爲ISession是靜態的,它不是線程安全的? – mattnss 2010-10-12 14:19:47

+0

@mattnss - 閱讀我也鏈接的答案。看起來如果你存儲會話而不是工廠本身,你可能會陷入困境。 – jfar 2010-10-12 14:42:37

+0

所以在我的代碼ive張貼,我只存儲SessionFactory在一個靜態變量,所以它應該是線程安全的? – mattnss 2010-10-13 18:38:45

1

從jfar開始閱讀一篇文章,我想我最終還是自學了一些關於這個主題的文章(或者投我的極點),並發現了一些很好的文章,闡述了NHibernate計劃的夏天是如何工作的。在Google上查找更多關於NHibernate和Contextual Sessions的詳細信息幫助我更好地掌握了該主題。我仍然對NHibernate(以及一般的網絡編程)很陌生,所以如果這個問題和答案看起來很簡單,請耐心等待。

看來NHibernate計劃的夏天是線程安全的。我的解釋將引用上面我的代碼示例中的名稱。 SessionFactory變量是靜態的,所以它可以從每個線程訪問,但是它是一個線程安全對象(正如前面提到的,ISession不是線程安全的)。 NHibernateSessionPerRequestModule建立兩個事件,這些事件將在Web請求(Application_BeginRequest)和一個(Application_EndRequest)的末尾觸發。 Application_BeginRequest將獲取一個ISession對象,然後您可以將它綁定到當前上下文。這有助於確保ISession對象用於Web請求的持續時間並僅用於該線程。 Web請求開始後,ISession可以通過.GetCurrentSession()進行檢索,以與_companyRepository一起使用。 Application_BeginRequest也會爲你開始交易。 Application_EndRequest將取消綁定ISession對象,在Web請求結束時提交所有更改並關閉ISession。

彼得·威格爾有一篇文章,顯示如何實現會話管理一個類似的例子: http://pwigle.wordpress.com/2008/11/21/nhibernate-session-handling-in-aspnet-the-easy-way

在那篇文章在Global.asax用於綁定和解除綁定,而不是創建一個IHttpModule的指定事件。

Ayende有一個使用的HttpContext管理您的iSessions一個乾淨的例子:如果我是大錯特錯和或我不理解的東西,請隨時插話,但據我可以告訴 http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx

只要不同的ISession綁定到每個線程上下文,它就會是線程安全的(除非需要有一個跨線程的ISession)。