如何使用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); } }