zoukankan      html  css  js  c++  java
  • NHibernate的Session管理策略和NHibernateHelper

    声明

    本篇中提到的Session,并非是Asp.NET中的Session,而是NHibernate中ISession。

    本篇假设读者已经对NHibernate的有一定的了解,已经成功持久化过领域模型。

    你不需要亲自用复制本篇的代码去调试,因为本篇的代码并不全,最后也有提供下载。

    本篇中的单元测试用到了NUnit,如果你使用其他框架也并不影响理解。

    正文 开门见山

    在ASP.NET中,如果我们希望每一个HTTP的请求只打开一个Session,在请求结束时关闭这个Session。

    也就是在请求期间,只用到这一个Session。或许我们可以称他为“one session per request”。

    这样做得好处是,你可以更容易地使用延迟加载,因为当领域模型传到表示层时,ISession在表示层仍然是打开的,并再请求结束后自动销毁。

    另外在单元测试时,并不一定有HTTP的请求,所以需要用另一种策略代替。

    作法:

    我们会在ASP.NET应用程序中这样使用

    HttpContext context = HttpContext.Current;
    if (context.Items["nhsession"] == null)
    {
            context.Items["nhsession"] = sessionFactory.OpenSession();
    }
    return context.Items["nhsession"] as ISession;


    以上代码意思是:我们需要Session时,就从web的上下文中取,一个请求中第一次会打开一个Session并保存再web上下文,以后就不再新打开了。

    但是有了这样的一个GetSession方法后,并不代表万事大吉了。

    下面来看一下单元测试:

    [Test]
    public void GetSessionTest()
    {
        ISession session=  NHibernateHelper.GetSession();
    }

    报错了,未将对象引用到实例,是哪个对象呢?HttpContext.Currtent为null。

    因为建立的是类库,这里并没有web的上下文。那怎么办呢?

    所以在这里我使用两套Session策略

    1、在Web应用程序中,就使用刚才提到的策略。

    2、在WinForm或单元测试中,使用另一种策略,每个线程用一个Session。

    其实在NHibernate文档中也有提到,在1.2以后的版本中,增加了一个GetCurrentSession()的方法,用于获取当前Session,这个上下文只支持一个ISessionFactory。你必须自己通过CurrentSessionContext类中的静态方法手动的把ISession实例绑定或者取消绑定到当前上下文。

    修改代码

            private static void BindContext()
            {
                if (!CurrentSessionContext.HasBind(sessionFactory))
                {
                    CurrentSessionContext.Bind(sessionFactory.OpenSession());
                }
            }
    
            private static void UnBindContext()
            {
                if (CurrentSessionContext.HasBind(sessionFactory))
                {
                    CurrentSessionContext.Unbind(sessionFactory);
                }
            }
    
            public static ISession GetCurrentSession()
            {
                BindContext();
                return sessionFactory.GetCurrentSession();
            } 


    这样做可以避免在代码中自己实现策略模式与IOC,NHibernate已经帮我们做好了。

    修改hibernate.cfg.xml配置文件,加入一个属性<property name="current_session_context_class">web</property>,修改这个属性就可以修改Session策略。

    也可以定义在代码中。

    sessionFactory = new Configuration().Configure()
                    .SetProperty("current_session_context_class", currentSessionContextClass.ToString())
                    .BuildSessionFactory();
    
    
    
        /// <summary>
        /// 当前Session上下文模式
        /// 特定环境下,当前Session保存在特定的上下文中
        /// </summary>
        public enum CurrentSessionContextClass
        {
            managed_web,
            call,
            thread_static,
            web
        }


    现在,我们就可以在web应用程序中将参数设置为web,而单元测试中将参数设置为thread_static。

            void Application_Start(object sender, EventArgs e)
            {
                // 在应用程序启动时运行的代码
                NHibernateHelper.Instance(CurrentSessionContextClass.web);
            }
            ISession session;
            [SetUp]
            public void Setup()
            {
                NHibernateHelper.Instance(CurrentSessionContextClass.thread_static);
                session = NHibernateHelper.GetCurrentSession();
            }

    下载:

     最后分享一个相关的NHibernateHelper文件

  • 相关阅读:
    抽取幸运观众
    随机产生139开头的电话号码
    脚本同步服务器系统时间
    判断网页是否存活
    nginx 添加到环境变量中
    spring boot helloworld
    IDEA 2019.3.3 Maven配置
    Window IDEA ULTIMATE 2019.3.3 安装&配置
    centos 7 Jenkins版本升级
    window 10 vscode+vue配置
  • 原文地址:https://www.cnblogs.com/13yan/p/3083552.html
Copyright © 2011-2022 走看看