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

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

  1. java成神之——ImmutableClass,null检查,字符编码,defaultLogger,可变参数,JavaScriptEngine,2D图,类单例,克隆,修饰符基本操作

    ImmutableClass null检查 字符编码 default logger 函数可变参数 Nashorn JavaScript engine 执行脚本文件 改变js文件输出流 全局变量 2D图 ...

  2. 转 java 类 单例

    转 单例概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一 ...

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

    eval与exec内置方法 将字符串作为执行目标,得到响应结果 eval常用作类型转换:该函数执行完有返回值 exec拥有执行更复杂的字符串:可以形成名称空间 eval内置函数的使用场景:   1.执 ...

  4. Python-元类 单例

    2.元类 用于创建类的类 叫元类 默认元类都是type 主要控制类的创建__init__ 类的实例化__call__ 3.单例 一个类只有一个实例 什么时候用,大家公用一个打印机,没有必要每个人创建新 ...

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

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

  6. PHP PDO类 单例

    <?php /*//pdo连接信息 $pdo=array("mysql:host=localhost;dbname=demo;charset=utf8","root ...

  7. iOS中编写单例类的心得

    单例 1.认识过的单例类有哪些: NSUserDefaults.NSNotificationCenter.NSFileManager.UIApplication 2.单例类 单例类某个类在代码编写时使 ...

  8. python__基础 : 类的__new__方法与实现一个单例

    __new__ : 这个方法的作用主要是创建一个实例,在创建实例时首先会调用 __new__方法 ,然后调用__init__对实例进行初始化, 如果想修改 __new__ 这个方法,那么最后要 ret ...

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

    // 在一个对象需要重复使用,并且很频繁时,可以对对象使用单例设计模式 // 单例的设计其实就是多alloc内部的allocWithZone下手,重写该方法 #pragma Person.h文件 #i ...

随机推荐

  1. WIN7笔记本显示连接不可用

    如图所示,找不到任何无线网络 解决方法: 不小心把无线关掉而已,笔记本键盘上F5~F12找看看有没有无线标志,有的话要先按下 Fn键不放,再按下那个有无线标志的Fn键.

  2. bzoj2019 [Usaco2009 Nov]找工作

    Description 奶牛们没钱了,正在找工作.农夫约翰知道后,希望奶牛们四处转转,碰碰运气.而且他还加了一条要求:一头牛在一个城市最多只能赚D(1 <= D <= 1,000)美元,然 ...

  3. 使用 APPLY

    原文地址:http://technet.microsoft.com/zh-cn/library/ms175156(v=SQL.105).aspx 使用 APPLY 运算符可以为实现查询操作的外部表表达 ...

  4. Android新浪微博客户端(一)——主框架搭建

    原文出自:方杰| http://fangjie.info/?p=62 转载请注明出处 提前声明的是,我是按照Ivan的这套教程学下来的. 首先,对于任何应用我们都需要建立一套消息处理机制,就是当用户在 ...

  5. 接上一篇博客(解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match. )

    解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variabl ...

  6. [OGRE]看备注学编程(02):打地鼠01-布置场地九只地鼠

    项目下载地址:http://download.csdn.net/detail/wxg694175346/6340347 头文件ShrewMouseApplication.h: #ifndef __Sh ...

  7. resin config 中文(resin.xml)

    <!-- - Resin 3.1 配置文件. --> <resin xmlns="http://caucho.com/ns/resin" xmlns:resin= ...

  8. UDP C/S编程

    UDP C/S编程的步骤如下图所示与TCP C/S通信的区别在于:服务端没有设置监听和等待连接的过程.客户端没有连接服务端的过程.基于UDP的通信时不可靠地,面向无连接的,发送的数据无法确切知道对方收 ...

  9. 用ueditor上传图片、文件等到七牛云存储

    ueditor上传文件,是用数据流的形式上传的. 而七牛云存储官方文档中,只提供了文件路径上传的方式. 但是,仅仅是在官方文档中写了这一种方式. 事实上,利用VS的对象管理器,打开Qiniu的dll, ...

  10. EF中的自动追踪与代理

    自动追踪 EF框架会自动追踪实体的变化(通过比较实体的当前值与原始值). 默认情况下,以下方法会自动触发实体变化的追踪 DbSet.Find DbSet.Local DbSet.Remove DbSe ...