2011-03-10 21 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实例可能不是您认为的那样。所以要注意如何/何时注入此属性=>从您显示的代码中不清楚。