我的NHibernate会话管理设置如下:
protected MvcApplication()
{
BeginRequest += delegate
{
NHibernateSessionManager.Instance.OpenSession();
};
EndRequest += delegate
{
NHibernateSessionManager.Instance.CloseSession();
};
}
当我需要保存到数据库时,我创建了一个看起来像这样的ActionFilterAttribute:
public class TransactionAttribute:ActionFilterAttribute { 私人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]添加到我的action方法中。这似乎适用于初始测试,但我尝试在HttpWebRequest使用多次从另一个应用程序调用一个动作方法,我遇到了问题。使用Fiddler进行测试我设置了一个POST请求,然后快速连续关闭它们,它显示以下内容:
红色是我认为与线程有关的各种错误。
我的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不应该存在?或者他们是共享还是什么?
有人可以开导我吗?
答案 0 :(得分:5)
来自release notes of ASP.NET MVC 3:
的引用在以前的ASP.NET MVC版本中, 每个人都创建了动作过滤器 除少数情况外请求。这个 行为从未得到保证 行为,但仅仅是一个实现 细节和过滤器合同 是认为他们无国籍。在 ASP.NET MVC 3,过滤器的缓存更多 积极。因此,任何习惯 不正确存储的动作过滤器 实例状态可能会被破坏。
这基本上意味着您的操作过滤器中的_currentTransaction
实例可能不是您认为的那样。所以要小心这个属性如何/何时注入=>你所展示的代码并不清楚。