简体   繁体   中英

How to implement session-per-request pattern in asp.net mvc with Nhibernate

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();

Store it in the HttpContext.

Add this to your 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();
    }

And here is the component registration

public class SessionInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container
            .Register(Component.For<ISession>().UsingFactoryMethod(() => MvcApplication.CurrentSession)
            .LifeStyle
            .PerWebRequest);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM