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缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...
随机推荐
- Linux的yum源的配置
yum实际上是管理的rpm软件包 只要连接网络就可以使用在线的yum源,不用配置本地yum源 网络yum源/etc/yum.repos.d/fedora.repo(Fedora)[fedora]nam ...
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition)
A.暴力枚举,注意游戏最长为90分钟 B.暴力,c[l]++,c[r]--,记录中间有多长的段是大小为n的,注意特判m=0的情况 C.暴力枚举,我居然一开始没想出来!我一直以为每次都要统计最大的,就要 ...
- PHP flush sleep 输出缓存控制详解
1 2 3 4 5 6 ob_start,flush,ob_flush for($i=0;$i<</SPAN>10;$i++) { echo $i.''; flush(); slee ...
- solr异常解决
使用solr1.4跟solr3.1时,配置了个唯一id类型是sint 或者int,启动时在tomcat后台就会抛出这个异常: org.apache.solr.common.SolrException: ...
- 来自HeroKu的HTTP API 设计指南(中文版)
原文转自:http://get.jobdeer.com/343.get 来自HeroKu的HTTP API 设计指南(中文版) 翻译 by @Easy 简介 本指南中文翻译者为 @Easy ,他是国内 ...
- source insight 相对路径
source insight项目 在移动到另外一个地方时,会因为之前是绝对路径而导致,项目中的文件都不可用,需要重新把这些文件添加一遍. 这是个令人讨厌的事情. 解决办法为创建项目时设定为绝对路径.方 ...
- select 通过jq赋值
<select name="F_YSBAQLX" onchange="selectvalue()" id="lista" prompt ...
- HDU 2509 nim博弈
Be the Winner Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- POJ 1511 Invitation Cards (spfa的邻接表)
Invitation Cards Time Limit : 16000/8000ms (Java/Other) Memory Limit : 524288/262144K (Java/Other) ...
- SQLite手工注入方法小结
SQLite 官网下载:www.sqlite.org/download.html sqlite管理工具:http://www.yunqa.de/delphi/products/sqlitespy/in ...