且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用Nhibernate在ASP.NET MVC中实现按请求的会话模式

更新时间:2023-02-16 09:36:02

使线程安全的唯一方法是为每个请求创建一个新会话,您可以在NHibernate配置中对managed_web使用current_session_context_class属性. /p>

在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<ISessionFactory>().OpenSession(); 
}).As<ISession>().InstancePerHttpRequest();

I created the nhibernate session in Application_start event of global.asax file,the session is being passed to constructors of service methods.

In the service method I am using the session to do CRUD operations, this works fine.However, When multiple requests or parallel transactions occuring nhibernate is throwing some exceptions.After reading forums i came to know that Nhibernate session is not thread safe.How to make it thread safe and let my application (ASP.NET mvc) work with parallel trandsactions?

Only way to make it thread safe is to create a new session per each request, you could use current_session_context_class property to managed_web in NHibernate config.

In 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
    }

now when you want to access the session, you could use,

Global.SessionFactory.GetCurrentSession()

If you are using a DI container, it's usually built into the container,

For example for Autofac (see this question for more information),

containerBuilder.Register(x => {
    return x.Resolve<ISessionFactory>().OpenSession(); 
}).As<ISession>().InstancePerHttpRequest();