一步步学习NHibernate(6)——ISession的管理
请注明转载地址:http://www.cnblogs.com/arhat
今天老魏那个汗啊,我的ThinkPad的电源线不通电了,擦啊。明天还得掏银子买一个!心疼啊,原装的啊。不过话说回来,已经用了将近10年了,已经算是可以的的了。不过就是心疼啊!明天还得给我的Thinkpad找个小三,哎!
通过前面两章的学习,我们知道了爱NHibernate中的核心技术就是懒加载,这个懒加载技术主要作用于有关系的表中,比如多对一,一对多。通过懒加载技术,我们可以很容易的获得关联的数据,但是懒加载却是有一个缺点的,我们拿前面的例子来说,如果现在我们要获得一个班级中所有的学生信息,当学生表中的数据不是很多的情况下,那么还不怎么影响效率的,如果是1000条,但是我们只需要其中的两条,那么NHiberante不会非常智能的加载出来,而是把1000条数据全部加载进来,很显然这不是我们想要的结果了。
如何解决这问题呢,我们在后面的HQL中来解决这个问题,本章呢,主要和大家来讨论一下对NHibernate的ISession管理。由于在NHibernate中,ISessionFactory是一个重量级对象,不能用一次创建一次,而是要在整个应用程序中只创建一次,而ISession是一个轻量级的对象,但是确是线程不安全的,所以我们今天要讨论的问题就是如何来管理他们。
首先我们来先分析一下原来写的NHibernateHelper.cs
public static class NHibernateHelper
{
private static ISessionFactory factory = null;
static NHibernateHelper()
{
factory = new Configuration().Configure().BuildSessionFactory();
}
public static ISession OpenSession()
{
return factory.OpenSession();
}
}
}
在这个类中,我们把ISessionFactory定义成一个私有的静态变量,由于ISessionFactory是一个重量级对象,那么我们不能每次都要创建,这样浪费我们系统的资源的。所以,我们把它定义为一个静态的变量(当然,也可以使用单态来写)。然后我们在静态构造函数中通过Configuration读取配置文件并创建ISessionFactory对象,那么当程序运行的时候在内存中只有一个ISessionFactory对象了。
接着,我们写了一个静态的方法,这个方法用来得到一个ISession对象用来和数据库打交道。但是这里需要说明的是当每一次调用OpenSession这个方法的时候,ISessionFactory都会创建一个全新的ISession对象。当然提出这个问题并不是说这样不好,而是这样创建出来的ISession对象是无法控制业务逻辑中的事务的(下面将会提到)。首先我们来测试一下通过OpenSession创建出来的ISession对象是不是全新的。
我们在主程序中写一个测试的方法:
static void Main(string[] args)
{
NHibernate.ISession session1 = DAL.NHibernateHelper.OpenSession();
NHibernate.ISession session2 = DAL.NHibernateHelper.OpenSession();
Console.WriteLine(session1 == session2);
}

从上面打印出的结果,我们可以看出通过OpenSession来创建的ISession对象都是全新的。那么这样的话会产生一个非常严重的问题,就是上面老魏说的如果我们在一次业务逻辑中同时执行了多个数据库操作,而每一次都需要打开一个ISession,那么事务是无法控制这些操作的。尤其在Web开发中,我们很有可能在一次请求过程中,执行了多次数据库操作,而却只需要一个事务提交,那么OpensSession是无法达到我们的要求的。所以NHibenrate为我们提供了一个新的方法用来创建ISession,这个方法就是GetCurrentSession。通过这个方法创建的ISession的生命周期是在一个上下文中,也就是说这个方法创建的ISession和当前线程以及当前请求时绑定在一起的,只要线程和请求没有被释放,那么着整个执行期间都是用这一个ISession。那么很显然,GetCurrentSession正是我们需要的。
那么如何使用这个GetCurrentSession呢?我们需要在应用程序的配置文件中进行一个配置说明,现在我们打开App.config文件,给session-factory添加一个属性节点,内容如下:
<property name="current_session_context_class">thread_static</property>
如果我们在winform应用程序中,这属性的取值为”thread_static”,如果在web项目中,这个取值为“web”。只有我们设置了这个节点,那么我们才能使用这个方法。我们来更改一下NHibernateHelper这个方法。在提供一个方法用来获得GetCurrentSession得到的ISession对象。
public static ISession GetCurrentSession()
{
return factory.GetCurrentSession();
}
好,我们现在来测试一下这个方法,看看是否能过获得ISession对象。在出程序中,我们更改一下Main方法。
static void Main(string[] args)
{
Console.WriteLine(DAL.NHibernateHelper.GetCurrentSession().IsOpen);
}
运行结果如下:

哦,天啊,怎么会出现异常呢?我们会发现异常信息是”No Session bound to the current context”。没有一个Session和当前上下文绑定。这一点是初学者经常犯的一个错误,我们已经配置了App.config的信息,那么怎么会获得不到呢?大家从上面的信息可以知道,我们只是配置了”要”和当前的线程绑定,但是只是“要”还没有真正的绑定。需要我们来手动的进行一个绑定信息。
根据分析,我们来改写一下NHibernateHelper的方法,能够让我们的GetCurrentSession能够正确运行。
private static void BindSession()
{
if (!CurrentSessionContext.HasBind(factory))
{
CurrentSessionContext.Bind(factory.OpenSession());
}
}
public static ISession GetCurrentSession()
{
BindSession();
return factory.GetCurrentSession();
}
在NHibernateHelper中,我们添加一个方法,就是用来把ISession对象和当前上下文(thread或者是web请求)进行绑定,此时我们在调用GetCurrentSession之前,首先执行一下BindSession来绑定。
然后我们再次运行主程序来测试一下: 
没问题了,但是我们得到的这个ISession对象到底是不是同一个呢?我们再来测试一下,更改主程序代码:
static void Main(string[] args)
{
NHibernate.ISession session1 = DAL.NHibernateHelper.GetCurrentSession();
NHibernate.ISession session2 = DAL.NHibernateHelper.GetCurrentSession();
Console.WriteLine("两个Session是同一个吗?"+(session1 == session2));
}

很显然,两个ISession对象是同一个了!这样我们解决了上面我们提到的那个矛盾问题了。
在本章中,我们讨论了一下如何去管理ISession对象以及如何获得GetCurrentSession来获得同一个ISession对象,达到我们执行事务的目的。希望大家能够从本章中学到一点东西!但是老魏却是很认真的告诉大家,本章很重要哦!
一步步学习NHibernate(6)——ISession的管理的更多相关文章
- 一步步学习NHibernate(1)——NHibernate介绍
请注明转载地址:http://www.cnblogs.com/arhat 第十五章 从本章开始,老魏将给大家一起学习NHibernate这个流行的ORM框架,本来老魏想要和大家一起探讨微软的EF框架的 ...
- 一步步学习NHibernate(7)——HQL查询(1)
请注明转载地址:http://www.cnblogs.com/arhat 从本章开始,老魏带着大家来学习一下HQL语句.HQL语句NHibernate为我们提供的一种功能比较强大的查询语句,这个HQL ...
- 一步步学习NHibernate(5)——多对一,一对多,懒加载(2)
请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们建立了Student和Clazz之间的关联属性,并从Student(many)的一方查看了Clazz的信 ...
- 一步步学习NHibernate(4)——多对一,一对多,懒加载(1)
请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们学会如何使用NHibernate对数据的简单查询,删除,更新和插入,那么如果说仅仅是这样的话,那么NHi ...
- 一步步学习NHibernate(3)——NHibernate增删改查
请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,我们配置了以下NHibernate的运行环境, 并介绍了NHibernate的中两个非常中重要的接口"I ...
- 一步步学习NHibernate(9)——连接查询和子查询(1)
请注明转载地址:http://www.cnblogs.com/arhat 在前几章中,我们把HQL的基本查询学习了一下,但是只有基本查询很显然不能满足我们的需求,那么就需要一下复杂查询比如" ...
- 一步步学习NHibernate(8)——HQL查询(2)
请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,老魏带着大家学习了HQL语句,发现HQL语句还是非常不错的,尤其是在懒加载的时候,书写起来比较的舒服,但是这里老魏 ...
- 一步步学习NHibernate(2)——配置NHibernate的环境
请注明转载地址:http://www.cnblogs.com/arhat 第二章 环境搭建 在上一章中,我们知道了NHibernate是用来干什么的了,那么今天在本章中,我们开始搭建NHibernat ...
- 一步步学习NHibernate(10)——连接查询和子查询(2)
请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,老魏讲述了HQL的链接查询,本章呢,老魏开始讲述HQL的子查询.子查询在SQL中也是占据着非常重要的作用,如果没有 ...
随机推荐
- Making Use of Forms and Fieldsets
Making Use of Forms and Fieldsets So far all we have done is read data from the database. In a real- ...
- java技术栈:项目概述
学习使用java到现在也有三年多了,这三年基本是以项目驱动的方式学习,有好有坏,个人觉得好处在于,有一个清晰的目标让你解决,这会让你学习非常迅速有效.当然坏处就是片面,不成体系.这种学习方式在学校以小 ...
- 网页js生成当前年月日 星期
只需将下面代码插入需要显示日期的地方即可 <div style="color: brown; font-size: 10px;">今天是: <script lan ...
- Linux基础(一)
一.安装linux系统可以用的5种方法 1.光盘 2.硬盘 3.NFS 映像 4.FTP 5.HTTP 硬盘安装分两种情况: A.是从Win系统上安装 B.是从别的Linux启动安装 这里介绍大多数人 ...
- Phantomjs安装
环境:Centos 6.5 介绍:PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处 ...
- linux系统下搭建自己的web服务器
之前在windows 2008 server上搭建了一个用于测试的web服务器,但是在打开网站的时候特别的慢,尤其是图片的加载都会失败,当时以为是路径的问题,但是在服务器上自己打开都特别慢,自己实在找 ...
- springmvc错误 Spring3.X jdk8 java.lang.IllegalArgumentException
最近在学习springmvc--碰到一个特别蛋疼的错误 javax.servlet.ServletException: Servlet.init() for servlet springMVC thr ...
- linux shell if参数
shell 编程中使用到得if语句内判断参数 –b 当file存在并且是块文件时返回真 -c 当file存在并且是字符文件时返回真 -d 当pathname存在并且是一个目录时返回真 -e 当path ...
- java学习笔记3
今天在练习java中的javabean的使用中发现.usebean的 <jsp:setProperty property="id" name="user" ...
- 用dubbo+zookeeper+spring搭建一个简单的http接口程序
dubbo是一个分布式服务框架,是阿里巴巴开发的一个解决RPC远程调用优化的核心框架,包含负载均衡算法,能提高分布式系统的性能. zookeeper是hadoop的一个子项目,主要用来解决分布式系统的 ...