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

时间: 2024-08-05 02:23:46

NHibernate 帮助类(单例实际运用)的相关文章

音频类 单例

.h文件 #import <Foundation/Foundation.h> @interface PLMsoundTool : NSObject<NSCopying> - (void)playSongWithName:(NSString *)name; + (instancetype)shareSoundTool; @end .m文件 #import "PLMsoundTool.h" #import <AudioToolbox/AudioToolbox.

正则表达式工具类单例

/// <summary> /// 正则表达式工具类单例 /// </summary> public class RegexTool { private static volatile RegexTool regex = null; private static object syncRoot = new Object(); /// <summary> /// 注册需要转换的类型 /// </summary> private RegexTool() { }

转 java 类 单例

转 单例概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Pr

Python-元类 单例

2.元类 用于创建类的类 叫元类 默认元类都是type 主要控制类的创建__init__ 类的实例化__call__ 3.单例 一个类只有一个实例 什么时候用,大家公用一个打印机,没有必要每个人创建新的打印机对象 共用一个对象即可 =============================== 元类是什么? 源自一句话:在python中,一切皆对象,而对象都是由类实例化得到的 本质上元类也是一个类,元类是用于实例化其他类 class Dog: def __init__(self): print(

29 内置方法 eval | exec 元类 单例

eval与exec内置方法 将字符串作为执行目标,得到响应结果 eval常用作类型转换:该函数执行完有返回值 exec拥有执行更复杂的字符串:可以形成名称空间 eval内置函数的使用场景:   1.执行字符串会得到相应的执行结果   2.一般用于类型转化,得到dict.list.tuple等 dic_str = "{'a': 1, 'b': 2, 'c': 3}" print(eval(dic_str)) list_str = "[1, 2, 3, 4, 5]" p

【C#】类单例 可以解决全局变量的问题

单件模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点. 知道 详解

类单例

+ (id)sharedRequest { //利用gcd创建一个单例模式 用来上传图片 static DVHttpConnectRequest *connectRequest = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ connectRequest = [[DVHttpConnectRequest alloc]init]; }); return connectRequest;

函数装饰器和类装饰器实现单例类

单例类,指的是这个类只能创建一个实例,创建完成后,其他类实例都无法再创建.今天我们来看一下,使用函数装饰器和类装饰器怎么实现这种特殊一点的类. 函数装饰器实现 装饰器算是类里面比较难的内容之一,但是实际上它的思想并不复杂.简单点说,就是在你原来内容的基础上,在外面给你加点东西,实现类似装饰的效果.但是它是怎么实现的呢?一般来说,都是通过拦截函数调用来实现的,比如:用装饰器装饰函数的时候,它拦截函数调用,装饰类的时候,它拦截类实例的创建调用,即拦截类初始化__init__函数.知道这个原理以后,我

OC中的单例设计模式及单例的宏抽取

1 // 在一个对象需要重复使用,并且很频繁时,可以对对象使用单例设计模式 2 // 单例的设计其实就是多alloc内部的allocWithZone下手,重写该方法 3 4 #pragma Person.h文件 5 6 #import <Foundation/Foundation.h> 7 @interface Person : NSObject <NSCopying,NSMutableCopying> 8 + (instancetype)sharePerson; // 给类提供一