nhibernate中session是线程不安全的,而且每次数据库操作 请求创建session时对性能有些影响。在windows应用中可以通过 [threadstatic]特性很简单的就可以实现线程安全,而在web中可以通过将session与用于请求httpcontext绑定实现线程安全,并且用户当前请求时只有一个session。代码如下:
isessionmanage.cs
using system;
using nhibernate;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:主要用于封装第三方类库操作数据库的session类,现主要用于封装nhibernate中的session
/// </summary>
public interface isessionmanage
{
/// <summary>
/// 获取session的一个实例
/// </summary>
/// <returns>返回实现nhibernate.isession接口的类</returns>
isession get();
/// <summary>
/// 设置session的一个实例
/// </summary>
/// <param name="session">实现nhibernate.isession接口的类</param>
void set(isession session);
}
}
--------------------------------------------
webnhsession.cs
using system;
using system.web;
using nhibernate;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:此类用于web应用,nhibernate提供的session有两个缺陷:
/// 一方面是线程不安全的,另一方面每次数据库操作创建一个session对程序性能有影响。
/// 因此通过将session绑定到httpcontext上,这样每个用户具有唯一的一个session,而且
/// 在用户的请求结束后关闭session并自己释放掉。
/// </summary>
public class webnhsession : isessionmanage
{
public webnhsession()
{
}
/// <summary>
/// 获取存储到httpcontext中的实现nhibernate.isession接口的类实例
/// </summary>
/// <returns>实现nhibernate.isession接口的类实例,当用户之前没有调用set方法会返回null</returns>
public isession get()
{
return (isession)httpcontext.current.items[sessionconfigmanage.sessionsourceitemname];
}
/// <summary>
/// 存储实现nhibernate.isession接口的类实例到httpcontext中
/// </summary>
/// <param name="session">实现nhibernate.isession接口的类实例</param>
public void set(isession session)
{
if (session != null)
{
httpcontext.current.items.add(sessionconfigmanage.sessionsourceitemname, session);
}
else
{
httpcontext.current.items.remove(sessionconfigmanage.sessionsourceitemname);
}
}
}
}
---------------------------------------------
winformnhsession.cs
using system;
using nhibernate;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:此类用于windows应用,nhibernate提供的session有两个缺陷:
/// 一方面是线程不安全的,另一方面每次数据库操作创建一个session对程序性能有影响。
/// 因此通过线程变量获取一个nhibernate session的多个线程安全的实例,而且线程变量使用后即释放掉。
/// </summary>
public class winformnhsession : isessionmanage
{
[threadstatic]
private static isession _threadsession = null;
public winformnhsession()
{
}
/// <summary>
/// 获取存储到线程变量中的实现nhibernate.isession接口的类实例
/// </summary>
/// <returns>实现nhibernate.isession接口的线程安全的类实例,当用户之前没有调用set方法会返回null</returns>
public isession get()
{
if (_threadsession != null)
{
if (_threadsession.isconnected)
{
_threadsession.reconnect();
}
}
return _threadsession;
}
/// <summary>
/// 存储实现nhibernate.isession接口的类实例到线程变量中
/// </summary>
/// <param name="session">实现nhibernate.isession接口的类实例</param>
public void set(isession session)
{
if (_threadsession.isconnected)
{
session.disconnect();
}
_threadsession = session;
}
}
}
----------------------------------------------
sessionfactory.cs
using system;
using system.runtime.remoting;
using nhibernate;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:管理多个实现isessionmanage接口的类工厂,根据读取的要加载的类名称信息,进行动态的创建session
/// </summary>
public class sessionfactory
{
private static isession session = null;
private static isessionmanage sessionmanage = null;
static sessionfactory()
{
init();
}
/// <summary>
/// 获取实现nhibernate.isession接口的session实例
/// </summary>
/// <returns>返回实现nhibernate.isession接口的类实例</returns>
public static isession getsession()
{
session = sessionmanage.get();
if (session == null)
{
session = nhibernatesession.getnhibernatesession();
sessionmanage.set(session);
}
return session;
}
private static void init()
{
system.reflection.assembly ass = system.reflection.assembly.load(sessionconfigmanage.assemblyname);
sessionmanage = (isessionmanage)ass.createinstance(sessionconfigmanage.sessionsourceitemname);
}
}
}
----------------------------------------------
nhibernatesession.cs
using system;
using system.data;
using system.collections.generic;
using system.text;
using nhibernate;
using nhibernate.cfg;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:加载嵌入资源(xml配置文件),打开一个sessionfactory,获取nhibernate的session实例
/// </summary>
public class nhibernatesession
{
private static configuration cfg = null;
private static isessionfactory sessionfactory = null;
static nhibernatesession()
{
cfg = new configuration().configure();
sessionfactory = cfg.buildsessionfactory();
}
/// <summary>
/// 获取nhibernate的session实例
/// </summary>
/// <returns></returns>
public static isession getnhibernatesession()
{
return sessionfactory.opensession();
}
}
}
---------------------------------------------
sessionconfigmanage.cs
using system;
using system.collections.generic;
using system.text;
using system.configuration;
namespace commercial.jwsoft.framework.persistence.sessionmanage
{
/// <summary>
/// 功能:根据类库的应用环境不同(windows应用还是web应用),动态创建类实例
/// 日期:2006-08-24
/// 作者:郭少宏
/// </summary>
public class sessionconfigmanage
{
private const string session_item_name = "sessionitemname";
private static object _locker = new object();
private static string _sessionitemname = string.empty;
private static string _assemblyname = string.empty;
static sessionconfigmanage()
{
string configstring = configurationmanager.appsettings[session_item_name];
string[] arr = configstring.split(',');
_sessionitemname = arr[0];
_assemblyname = arr[1];
}
/// <summary>
/// 获取配置文件中名为session_item_name配置节的信息,记录的要加载的sessionmanage的类全称
/// </summary>
/// <returns>实现isessionmanage接口的类的名称</returns>
public static string sessionsourceitemname
{
get
{
lock (_locker)
{
return _sessionitemname;
}
}
}
/// <summary>
/// 获取配置文件中名为session_item_name配置节的信息,记录的要加载的sessionmanage的类全称
/// </summary>
/// <returns>实现isessionmanage接口的类的程序集名称</returns>
public static string assemblyname
{
get
{
lock (_locker)
{
return _assemblyname;
}
}
}
}
}
在web.config文件中的配置节如下:
<appsettings>
<!---->
<!--在web应用中加载的获取session的类名称-->
<add key="sessionitemname" value="commercial.jwsoft.framework.persistence.sessionmanage.webnhsession,jwframework"/>
<!--在windows应用中加载的获取session的类名称-->
<!--<add key="sessionitemname" value="commercial.jwsoft.framework.persistence.sessionmanage.winformnhsession,jwframework"/>-->
</appsettings>
在global.asax中添加如下代码:
/// <summary>
/// 当用户断开请求时用来关闭用户请求的session的连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void session_end(object sender, eventargs e)
{
nhibernate.isession session = commercial.jwsoft.framework.persistence.sessionmanage.sessionfactory.getsession();
if (session != null)
{
session.close();
}
}
新闻热点
疑难解答