如何使用Nhibernate在asp.net mvc中实现session-per-request模式
我在global.asax文件的Application_start事件中创建了nhibernate会话,该会话被传递给服务方法的构造函数。
在服务方法我使用会话来做CRUD操作,这很好。但是,当多个请求或并行事务发生时,nhibernate会抛出一些exception。阅读论坛后我才知道Nhibernate会话不是线程安全的。如何使它的线程安全,让我的应用程序(ASP.NET mvc)使用并行trandsactions?
使线程安全的唯一方法是为每个请求创建一个新会话,您可以在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(有关更多信息,请参阅此问题 ),
containerBuilder.Register(x => { return x.Resolve().OpenSession(); }).As().InstancePerHttpRequest();
将其存储在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().UsingFactoryMethod(() => MvcApplication.CurrentSession) .LifeStyle .PerWebRequest); } }