【问题标题】:How to implement session-per-request pattern in asp.net mvc with Nhibernate如何使用 Nhibernate 在 asp.net mvc 中实现每请求会话模式
【发布时间】:2016-10-19 14:50:54
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案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();
    

    【讨论】:

    • 不使用依赖注入如何从 global.asax 获取会话到数据访问层?
    • Global.SessionFactory.GetCurrentSession()
    • 如果数据访问层在不同的项目中?如何访问它。
    • 您可以参考该项目,或者您可能要考虑使用 DI
    【解决方案2】:

    将其存储在 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);
        }
    }
    

    【讨论】:

    • 如果我们将会话存储在httpcontext中,我们如何从数据访问层项目中访问它。我没有使用依赖注入。请建议
    • 您混淆了几件事。 1.你不能在Application_Start中启动会话,并为每个进来的用户使用它。这就是你在Application_BeginRequest中启动会话的原因。您希望将会话范围限定为 http 请求。 2. 如果您不打算从多个线程更新会话,则会话不必是线程安全的。在 Application_Start 中,您要构建您的 SessionFactory。
    • 如果您不使用 DI,只需将 MvcApplication.CurrentSession 传递给您的控制器构造函数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2010-11-30
    • 2012-06-30
    相关资源
    最近更新 更多