如何使用Nhibernate在asp.net mvc中实现session-per-request模式

时间:2016-06-17 17:25:08

标签: c# asp.net asp.net-mvc session nhibernate

我在global.asax文件的Application_start事件中创建了nhibernate会话,会话被传递给服务方法的构造函数。

在服务方法中我使用会话进行CRUD操作,这很好。但是,当多个请求或并行事务发生时,nhibernate会抛出一些异常。阅读论坛后我才知道Nhibernate会话不是线程安全的。如何使其线程安全,让我的应用程序(ASP.NET mvc)与并行trandsactions一起工作?

2 个答案:

答案 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);
    }
}