NHibernate系列文章十七:NHibernate Session管理(附程序下载)
摘要
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管理(附程序下载)的更多相关文章
- NHibernate系列文章二十七:NHibernate Mapping之Fluent Mapping基础(附程序下载)
摘要 从这一节起,介绍NHibernate Mapping的内容.前面文章都是使用的NHibernate XML Mapping.NHibernate XML Mapping是NHibernate最早 ...
- NHibernate系列文章二十五:NHibernate查询之Query Over查询(附程序下载)
摘要 这一篇文章介绍在NHibernate 3.2里引入的Query Over查询,Query Over查询跟Criteria查询类似.首先创建IQueryOver对象,然后通过调用该对象的API函数 ...
- NHibernate系列文章二十六:NHibernate查询之SQL Query查询(附程序下载)
摘要 NHibernate在很早的版本就提供了SQL Query(原生SQL查询),对于很复杂的查询,如果使用其他的查询方式实现比较困难的时候,一般使用SQL Query.使用SQL Query是基于 ...
- NHibernate系列文章十九:NHibernate关系之多对多关系(附程序下载)
摘要 NHibernate的多对多关系映射由many-to-many定义. 从这里下载本文的代码NHibernate Demo 1.修改数据库 添加Product表 添加ProductOrder表 数 ...
- 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- NHibernate系列文章十六:使用程序集管理NHibernate项目(附程序下载)
摘要 在实际的项目中,经常是将NHibernate的实体关系映射类做成独立的工程(assembly dll),只对外提供Session调用的接口.这个程序集作为数据访问层,可以被上面的多个工程(ASP ...
- NHibernate系列文章二十三:NHibernate查询之Criteria查询(附程序下载)
摘要 上一篇文章介绍了NHibernate HQL,他的缺点是不能够在编译时发现问题.如果数据库表结构有改动引起了实体关系映射的类有改动,要同时修改这些HQL字符串.这篇文章介绍NHibernate面 ...
- NHibernate系列文章十八:NHibernate关系之一对多(附程序下载)
摘要 这篇文章介绍NHibernate最实用的内容:关系映射. NHibernate的关系映射方式有三种: Set:无序对象集合,集合中每一个元素不能重复. List:有序对象集合,集合中的元素可以重 ...
- NHibernate系列文章九:NHibernate对象二级缓存上
摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...
随机推荐
- B - 搬寝室
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Pract ...
- Day17_集合第三天
1.HashSet类(掌握) 1.哈希值概念 哈希值:哈希值就是调用对象的hashCode()方法后返回的一个int型数字 哈希桶:简单点理解就是存储相同哈希值对象的一个容器 1. ...
- ps esc 问题
最近经常发现esc键突然变得不能用了.主要是使用搜狗输入法时使用esc键取输错的字,因此还以为是搜狗的问题,后来突然想到可能是因为打开某个软件导致esc不能用,最后发现居然是ps,在网上查了后发现很多 ...
- 修改mysql用户名密码 和 PHPmysqlAdmin对应密码修改
本地的mysql运行时,可能会用到修改用户名密码: mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('输入新密码');不存在修改用户啊 ...
- 计算std:string的字节长度
如果项目本身是使用 Unicode 字符集和utf8编码,std::string的length(),size()甚至是c的strLen取到的都是字节长度了,比如三个汉字,就是9, 以上情况不满足的话, ...
- android textview显示html问题
我在textivew中填充了html标签后,末尾端总是有2.3个空行.debug也没发现有什么换行符.空格符,后来查了半天html的标签,发现里面有个<div>标签,这个标签的作用是把内容 ...
- JAVA中精确计算金额BigDecimal
package com.chauvet.utils; import java.math.BigDecimal; import java.text.DecimalFormat; import java. ...
- LeetCode 【190. Reverse Bits】
Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...
- RabbitMQ中 exchange、route、queue的关系
从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心,下面我们就围绕这三个主要组件 从应用使用的角度全面的介绍如何利用Rabbit MQ构建 ...
- Qt之QComboBox(基本应用、代理设置)(转)
QComboBox下拉列表比较常用,用户可以通过选择不同的选项来实现不同的操作,如何实现自己的下拉列表呢? 很多人在问QComboBox如何设置选项的高度.代理等一些问题!今天就在此分享一下自己的一些 ...