摘要

NHibernate的Session的管理涉及到NHibernate的两个最重要的对象ISessionFactory和ISession。ISessionFactory的生成非常消耗资源,通常都在应用程序启动的时候生成,并使用单例模式,被应用程序的所有线程共享。ISession的生成虽然没有ISessionFactory那么消耗资源,但是Session中保存了一级缓存池,如果每次使用到ISession的时候都生成新的ISession对象,而且这样的操作频率很大的时候,也会一定程度上大量消耗内存资源。NHibernate提供CurrentSessionContext对象,将ISession与当前应用的上下文环境进行绑定,先生成ISession,并与CurrentSessionContext绑定,后面直接从CurrentSessionContext中取ISession,可以显著提高执行效率。

本篇文章全部代码可以到NHibernate Demo下载。

1. ISession管理过程

1)使用单例模式生成ISessionFactory对象。

2)在生成ISessionFactory对象的过程中,使用Configuration对象的CurrentSessionContext()方法,生成CurrentSessionContext。

CurrentSessionContext方法原型:

public static Configuration CurrentSessionContext<TCurrentSessionContext>(this Configuration configuration) where TCurrentSessionContext : ICurrentSessionContext;

TCurrentSessionContext是泛型参数,必须继承ICurrentSessionContext接口。

ICurrentSessionContext接口有两个继承类:WebSessionContext和ThreadStaticSessionContext。在ASP.Net Web程序中使用WebSessionContext类,在Windows Form和控制台应用程序中使用ThreadStaticSessionContext。

3)通过ISessionFactory对象的ISessionFactory.OpenSession()方法生成ISession对象。

4)CurrentSessionContext类提供三个静态方法,Bind/UnBind/HasBind,用来管理CurrentSessionContext对象和ISession对象之间的关系。

下面是这三个方法的原型:

public static void Bind(ISession session);

public static ISession Unbind(ISessionFactory factory);

public static bool HasBind(ISessionFactory factory);

5)如果之前调用了Bind静态方法将ISession对象跟CurrentSessionContext进行绑定,那么调用HasBind方法返回true。此时可以使用ISessionFactory对象的GetCurrentSession方法,获得之前与CurrentSessionContext绑定的ISession对象。

6)ISesion对象用完后,需要调用CurrentSessionContext.Unbind静态方法将当前ISession与当前上下文环境解除绑定。并调用ISession对象的Close()方法关闭ISession对象。

下面是一个完整的ISessionFactory和ISession管理的类。

 using NHibernate;
using NHibernate.Cfg;
using NHibernate.Context;
using System;
using System.Web; namespace Demo.Service
{
/// <summary>
/// Manages the NHibernate session
/// </summary>
public class SessionManager
{
private static ISessionFactory SessionFactory { get; set; } public static string ConnectionString { get; set; } private static ISessionFactory GetFactory<T>() where T : ICurrentSessionContext
{
var cfg = new Configuration(); cfg.DataBaseIntegration(x => {
#if DEBUG
x.LogSqlInConsole = true;
#endif
if (!string.IsNullOrEmpty(ConnectionString)
&& ConnectionString.Trim() != "")
{
x.ConnectionString = ConnectionString;
}
}); cfg.Configure().CurrentSessionContext<T>();
return cfg.BuildSessionFactory();
} /// <summary>
/// Gets the current session.
/// </summary>
public static ISession GetCurrentSession()
{
if (SessionFactory == null)
{
SessionFactory = HttpContext.Current != null ? GetFactory<WebSessionContext>() : GetFactory<ThreadStaticSessionContext>();
} if (CurrentSessionContext.HasBind(SessionFactory))
{
return SessionFactory.GetCurrentSession();
} var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session); return session;
} /// <summary>
/// Closes the session.
/// </summary>
public static void CloseSession()
{
if (SessionFactory != null && CurrentSessionContext.HasBind(SessionFactory))
{
var session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null && session.IsOpen)
{
session.Close();
}
}
}

2. 在Asp.Net程序中管理ISession对象

Asp.Net的页面请求过程是无状态的,不能将ISession对象持久化到内存中。但是可以使用自定义的IHttpModule对象来实现:每生成一个HTTP请求,生成一个ISession。

     public class SessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += (sender, e) => SessionManager.CloseSession();
} public void Dispose()
{
}
}

HttpApplication.EndRequest事件在每次HttpRequest执行完毕之后调用,定义此事件用来关闭ISession对象。

在web.config文件中,添加HttpModule。

<system.webServer>
<modules>
<add name="SessionModule" type="Demo.Service.Infrastructure.SessionModule,Demo.Service"/>
</modules>
</system.webServer>

type的值由逗号隔开为两部分,前面部分是Module类的完整类名,后面部分是Module类所在的程序集名称。

3. 数据操作基础类的接口的实现

定义IService<T>接口。T是泛型参数,代表NHibernate映射类,必须是引用类型,因此添加where的class条件。

 using System.Collections.Generic;
using System.Linq; namespace Demo.Service.Infrastructure.Interface
{
public interface IService<T> where T : class
{
IList<T> GetAll();
IQueryable<T> Query();
T GetById(int id);
T LoadById(int id);
int Save(T obj, bool includeInTransaction = false);
void Update(T obj, bool includeInTransaction = false);
void Delete(int id, bool includeInTransaction = false);
}
}

定义实现类Service<T>

 using Demo.Service.Infrastructure.Interface;
using NHibernate;
using NHibernate.Linq;
using System;
using System.Collections.Generic;
using System.Linq; namespace Demo.Service.Infrastructure
{
public class Service<T> : IService<T> where T : class
{
protected ISession Session
{
get { return SessionManager.GetCurrentSession(); }
} public IList<T> GetAll()
{
IList<T> list = Session.CreateCriteria<T>().List<T>();
return list;
} public virtual IQueryable<T> Query()
{
var result = Session.Query<T>();
return result;
} public T GetById(int id)
{
T obj = Session.Get<T>(id);
return obj;
} public T LoadById(int id)
{
T obj = Session.Load<T>(id);
return obj;
} public int Save(T obj, bool includeInTransaction = false)
{
var identifier = Session.Save(obj);
if (!includeInTransaction)
{
Session.Flush();
}
return Convert.ToInt32(identifier);
} public void Update(T obj, bool includeInTransaction = false)
{
Session.SaveOrUpdate(obj);
if (!includeInTransaction)
{
Session.Flush();
}
} public void Delete(int id, bool includeInTransaction = false)
{
var obj = Session.Get<T>(id);
Session.Delete(obj);
if (!includeInTransaction)
{
Session.Flush();
}
}
}
}

在Insert/Update/Delete方法中添加includeInTransaction参数,如果是从存储过程调用,则传入true,否则用默认值false(立即写入数据库)。

结语

这篇文章介绍了NHibernate的ISessionFactory和ISession的管理方法,ISessionFactory使用单例模式进行创建和管理,ISession的管理基于NHibernate的内置CurrentSessionContext对象,使用该类的静态方法Bind、UnBind和HasBind方法进行ISession的管理。在Asp.Net工程和Windows Form工程中管理ISession的方法是不同的。介绍了在Asp.Net中如何通过自定义HttpModule实现ISession的管理,实现一个请求一个ISession。

下一篇文章开始介绍NHibernate的关系映射。

NHibernate系列文章十七:NHibernate Session管理(附程序下载)的更多相关文章

  1. NHibernate系列文章二十七:NHibernate Mapping之Fluent Mapping基础(附程序下载)

    摘要 从这一节起,介绍NHibernate Mapping的内容.前面文章都是使用的NHibernate XML Mapping.NHibernate XML Mapping是NHibernate最早 ...

  2. NHibernate系列文章二十五:NHibernate查询之Query Over查询(附程序下载)

    摘要 这一篇文章介绍在NHibernate 3.2里引入的Query Over查询,Query Over查询跟Criteria查询类似.首先创建IQueryOver对象,然后通过调用该对象的API函数 ...

  3. NHibernate系列文章二十六:NHibernate查询之SQL Query查询(附程序下载)

    摘要 NHibernate在很早的版本就提供了SQL Query(原生SQL查询),对于很复杂的查询,如果使用其他的查询方式实现比较困难的时候,一般使用SQL Query.使用SQL Query是基于 ...

  4. NHibernate系列文章十九:NHibernate关系之多对多关系(附程序下载)

    摘要 NHibernate的多对多关系映射由many-to-many定义. 从这里下载本文的代码NHibernate Demo 1.修改数据库 添加Product表 添加ProductOrder表 数 ...

  5. 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  6. NHibernate系列文章十六:使用程序集管理NHibernate项目(附程序下载)

    摘要 在实际的项目中,经常是将NHibernate的实体关系映射类做成独立的工程(assembly dll),只对外提供Session调用的接口.这个程序集作为数据访问层,可以被上面的多个工程(ASP ...

  7. NHibernate系列文章二十三:NHibernate查询之Criteria查询(附程序下载)

    摘要 上一篇文章介绍了NHibernate HQL,他的缺点是不能够在编译时发现问题.如果数据库表结构有改动引起了实体关系映射的类有改动,要同时修改这些HQL字符串.这篇文章介绍NHibernate面 ...

  8. NHibernate系列文章十八:NHibernate关系之一对多(附程序下载)

    摘要 这篇文章介绍NHibernate最实用的内容:关系映射. NHibernate的关系映射方式有三种: Set:无序对象集合,集合中每一个元素不能重复. List:有序对象集合,集合中的元素可以重 ...

  9. NHibernate系列文章九:NHibernate对象二级缓存上

    摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...

随机推荐

  1. ubuntu下安装svn服务器

    sudo apt-get install apache2 sudo apt-get install subversion sudo apt-get install libapache2-svn 其次, ...

  2. IOS 验证码

    将十六进制的字符串转化为UIImage 最近写一个项目,有验证码,但是接口返回的并不是验证码图片的URL,而是返回的字节数组16进制字符串.这样就需要把16进制字符串首先字节数组,其次再把字节数组转化 ...

  3. 日常笔记 ---- 图形学-Frenel函数材质球实现方式

    图形学-Frenel函数材质球实现方式   调个材质 大概公式 自发光= 自定义边光颜色* ((1-法线与视角方向点乘)的 自定义幂次方 ) 这个是比较简单方法   模型的法线与视角方向 角度越大 表 ...

  4. BZOJ 3809 莫队+(分块|BIT)

    #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> ...

  5. Linux中查看文件编码

    在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱 ...

  6. 第三个Sprint冲刺第四天

    讨论地点:宿舍 讨论成员:邵家文.李新.朱浩龙.陈俊金 讨论问题:强化界面功能

  7. Java数据结构和算法之链表

    三.链表 链结点 在链表中,每个数据项都被包含在‘点“中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LINK对象中 ...

  8. LintCode Binary Tree Maximum Path Sum

    Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. ...

  9. 关于配置服务器(IIS7)

    服务器Server2003 ,无限开机动画慢动作重播,一怒而重装server2008 然,重点就是系统装好了 IIS装好了 ,发布网站 开始各种错了!!! 1.第一个错 额,错误信息说 :由于权限不足 ...

  10. Java常用正则表达式验证工具类RegexUtils.java

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexUtils{ /** * 正则表达式 ...