我在global.asax文件的Application_start事件中创建了nhibernate会话,会话被传递给服务方法的构造函数。
在服务方法中我使用会话进行CRUD操作,这很好。但是,当多个请求或并行事务发生时,nhibernate会抛出一些异常。阅读论坛后我才知道Nhibernate会话不是线程安全的。如何使其线程安全,让我的应用程序(ASP.NET mvc)与并行trandsactions一起工作?
答案 0 :(得分:1)
使线程安全的唯一方法是为每个请求创建一个新会话,您可以在NHibernate配置中使用current_session_context_class
属性managed_web
。
在global.asax
中 protected void Application_BeginRequest(object sender, EventArgs e)
{
var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
var session = CurrentSessionContext.Unbind(SessionFactory);
//commit transaction and close the session
}
现在,当您想要访问会话时,可以使用
Global.SessionFactory.GetCurrentSession()
如果您使用的是DI容器,它通常内置于容器中,
例如,对于Autofac(有关详细信息,请参阅this question),
containerBuilder.Register(x => {
return x.Resolve<ISessionFactory>().OpenSession();
}).As<ISession>().InstancePerHttpRequest();
答案 1 :(得分:0)
将其存储在HttpContext中。
将此添加到您的global.asax
public static String sessionkey = "current.session";
public static ISession CurrentSession
{
get { return (ISession)HttpContext.Current.Items[sessionkey]; }
set { HttpContext.Current.Items[sessionkey] = value; }
}
protected void Application_BeginRequest()
{
CurrentSession = SessionFactory.OpenSession();
}
protected void Application_EndRequest()
{
if (CurrentSession != null)
CurrentSession.Dispose();
}
这是组件注册
public class SessionInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container
.Register(Component.For<ISession>().UsingFactoryMethod(() => MvcApplication.CurrentSession)
.LifeStyle
.PerWebRequest);
}
}