2011-03-10 56 views
4

我有我的NHibernate會話管理設置類似如下:MVC屬性中的HttpContext - 線程問題?

protected MvcApplication() 
    { 
     BeginRequest += delegate 
          { 
           NHibernateSessionManager.Instance.OpenSession(); 
          }; 
     EndRequest += delegate 
          { 

           NHibernateSessionManager.Instance.CloseSession(); 
          }; 
    } 

以及當我需要保存到數據庫中,我做了一個看起來像這樣的ActionFilterAttribute:

公共類TransactionAttribute:ActionFilterAttribute { private ITransaction _currentTransaction;

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     _currentTransaction = NHibernateSessionManager.Instance.CurrentSession.Transaction; 
     _currentTransaction.Begin(); 
    } 


    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     if (_currentTransaction.IsActive) 
     { 
      if (filterContext.Exception == null) 
       _currentTransaction.Commit(); 
      else 
      { 
       _currentTransaction.Rollback(); 
      } 
     } 
     _currentTransaction.Dispose(); 
    } 
} 

然後我可以在我的操作方法中添加[Transaction]。這似乎在初始測試中工作,但我然後嘗試使用HttpWebRequest多次調用另一個應用程序的操作方法,我有問題。使用Fiddler我設置測試POST請求,然後快速連續發射他們的時間,這表明了以下幾點: WebRequests

紅色的是一些我認爲是線程做各種錯誤。

我NHibernateSessionManager使用的HttpContext存儲這樣的會議:

public ISession CurrentSession 
    { 
     get { return (ISession)HttpContext.Current.Items["current.session"]; } 
     set { HttpContext.Current.Items["current.session"] = value; } 
    } 

因此,要固定它,我把我的事務代碼到我的BeginRequest和EndRequest方法 - 然後我能火過連續堆。

我的問題是 - 爲什麼這個修復它?我本來以爲我將不得不與此類似: 開始請求 - 打開會話 OnActionExecuting - 開始交易 動作代碼 OnActionExecuted - 提交交易 結束請求 - 關閉會話

而且這將是獨一無二的每個請求,所以它不應該互相干擾,因爲每個請求應該有不同的HttpContext不應該在那裏?或者他們分享什麼?

有人能夠啓發我嗎?從release notes of ASP.NET MVC 3

回答

5

報價:

在ASP.NET MVC的早期版本中, 行動過濾器每 請求創建,除了在少數情況下。這種行爲從來沒有保證 的行爲,但僅僅是一個實施 細節和過濾器 的合同被認爲是無狀態的。在ASP.NET MVC 3中,積極地緩存更多的過濾器 。因此,任何不正確地存儲 實例狀態的自定義 操作篩選器可能會中斷。

這基本上意味着您的操作篩選器中的_currentTransaction實例可能不是您認爲的那樣。所以要注意如何/何時注入此屬性=>從您顯示的代碼中不清楚。