zoukankan      html  css  js  c++  java
  • NHibernate 帮助类(单例实际运用)

    在NHibernate中,ISessionFactory是线程安全的,对应一个数据库。它是生成ISession的工厂。而ISession是线程不安全的。

      创建一个ISessionFactory需要消耗比较多的资源。因此,我们只在程序初始化的时候创建一次,以后就一直使用这个ISessionFactory。

      而ISession的创建只消耗很少的资源。因此我们可以随意创建。

    一、原始单例模式封装的ISessionFactory

      因此,对于ISessionFactory,我们使用饿汉单例模式实现它。

      原始饿汉单例模式封装ISessionFactory实例:

    复制代码
          //密封类
            public sealed class NSession
            {
                //私有、静态、只读
                private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
    
                //私有构造函数,防止new
                private NSession()
                {
    
                }
    
                public static ISessionFactory GetSessionFactory()
                {
                    return sessionFactory;
                }
            }
    复制代码

      OK,对于ISessionFactory,以上代码就能够保证,整个程序只有一个SessionFactory的实例了。

      虽然,上面的代码已经使用单例模式实现了SessionFactory只能保证只有一个实例。但是,实际上我们能够进一步封装,实现管理到 ISession。因为在我们的程序当中,我们实际上使用的是ISession。而我们要得到ISession对象,每次都要在代码里调用

      ISession iSession = NSession.GetSessionFactory().OpenSession();

      这样的代码来获得ISession对象。我们何不干脆封装到ISession呢?

    二、利用HttpContext绑定ISession

      上面说到,我们实际上要用到的是ISession对象而不是ISessionFactory对象。所以,我们干脆封装到ISession,实现更简单的调用。

      我们,先来看看以下代码的问题:

    复制代码
        //密封类
        public sealed class NSession
        {
            //私有、静态、只读
            private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
    
            //私有构造函数,防止new
            private NSession()
            {
    
            }
    
            //返回ISession
            public static ISession GetSession()
            {
                return sessionFactory.OpenSession();
            }
        }
    复制代码

      测试代码:

    复制代码
            public PersonModel GetPerson(int Id)
            {
                ISession iSession1 = NSession.GetSession();
                ISession iSession2 = NSession.GetSession();
                HttpContext.Current.Response.Write(object.ReferenceEquals(iSession1, iSession2));   //输出 False,这是两个ISession对象
                return iSession1.Get<PersonModel>(Id);
            }
    复制代码

      我们看到,假若我们想上面那种封装方法,只要调用了一次GetSession()方法,就会生成一个新的ISession对象,虽然这样 ISession占用的资源不多,但总感觉有多少浪费,我们何不将ISession绑定到HttpContext中,实现对于一次Http请求,只创建一 个ISession呢?

    复制代码
        //密封类
        public sealed class NSession
        {
            //私有、静态、只读
            private static readonly ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
    
            //私有构造函数,防止new
            private NSession()
            {
    
            }
    
            //获取ISession
            public static ISession GetSession()
            {
                HttpContext context = HttpContext.Current;
                ISession currentSession = context.Items["ISession"] as ISession;
                //如果对于本次请求的HttpContext里还没有ISession对象,才OpenSession(),同时存入HttpContext中,用于下次判断和Close()
                if (currentSession == null)
                {
                    currentSession = sessionFactory.OpenSession();
                    context.Items["ISession"] = currentSession;
                }
    
                return currentSession;
            }
    
            //关闭ISession
            public static void CloseSession()
            {
                HttpContext context = HttpContext.Current;
                ISession currentSession = context.Items["ISession"] as ISession;
                //如果对于本次请求还没有创建ISession对象,那就用不着关闭了
                if (currentSession != null)
                {
                    currentSession.Close();
                    context.Items.Remove("ISession");
                }
            }
    
            //关闭SessionFactory
            public static void CloseSessionFactory()
            {
                if (sessionFactory != null)
                {
                    sessionFactory.Close();
                }
            }
        }
    复制代码

      我们再来测试下:

    复制代码
            public PersonModel GetPerson(int Id)
            {
                ISession iSession1 = NSession.GetSession();
                ISession iSession2 = NSession.GetSession();
                HttpContext.Current.Response.Write(object.ReferenceEquals(iSession1, iSession2));   //输出 True,这是两个ISession对象
                return iSession1.Get<PersonModel>(Id);
            }
    复制代码

      这次是输出True了。说明,这两个是同一个对象。

      以上代码就实现了HttpContext与ISession对象挂钩,对于一次HttpContext只创建一个ISession。当请求响应 完毕,HttpContext里面的ISession就自动释放掉了。对于在请求响应未完毕之前,该ISession都一直处于打开状态(例如渲染视图 时),不影响操作。

      以上代码依赖于HttpContext,因此只适合于Web程序。

    三、非Web程序中封装ISession

      而对于在WinForm或控制台项目中,由于程序是跑在客户端上,一个客户端电脑,哪怕你Open好几百个ISession都没什么问题,只是要管理好ISessionFactory,因为ISessionFactory还是比较占用资源的。

      对于非Web程序中的NHibernate帮助类实现如下:

    复制代码
        public sealed class NSession
        {
         private static readonly ISessionFactory sessionFactory; static NSession() { sessionFactory = new Configuration().Configure().BuildSessionFactory(); } public static ISession GetSession() { return sessionFactory.OpenSession(); } public static void CloseSession(ISession currentSession) { if (currentSession != null) { currentSession.Close(); } } public static void CloseSessionFactory() { if (sessionFactory != null) { sessionFactory.Close(); } } }
    复制代码
  • 相关阅读:
    mysql备份还原
    java-mysql(3) 读写image
    java-mysql(2) Prepared statement
    java-mysql(1)
    jmeter报告分析工具
    浏览器下载img标签Base64图片
    Java定时器TimeTask
    js倒计时
    h5语音播放(移动端)
    Linux环境下在Tomcat上部署JavaWeb工程
  • 原文地址:https://www.cnblogs.com/liuguanghai/p/5031870.html
Copyright © 2011-2022 走看看