NHibernate中Session的处理 线程不安全
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();
}
}
NHibernate中Session的处理 线程不安全的更多相关文章
- Hibernate中Session与本地线程绑定
------------------siwuxie095 Hibernate 中 Session 与本地线程绑定 1.Session 类似于 JDBC 的连接 Connection 2.Session ...
- NHibernate中session.update()及session.merge()的区别
今天的工作中遇到一个奇怪的问题,如下: "a different object with the same identifier value was already associated w ...
- NHibernate中的API
本篇文章介绍的是NHibernate的各种API及其作用. 下图描述了NHibernate的API在分层架构中的作用,下面将进行详细说明. NHibernate的接口大致分为四类:1. 被应用程序调 ...
- NHibernate中,查询SqlServer数据库多个实体对象
关于datetime类型使用: Oracle: "and tb.EffectiveDate >= to_date(?,'yyyy-mm')" Sql: "an ...
- NHibernate 中删除数据的几种方法
今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...
- hibernate中session的获取使用以及其他注意事项
hibernate中session的获取使用以及其他注意事项 前言:工作时,在同时使用Hibernate的getSession().getHibernateTemplate()获取Session后进行 ...
- 总结NHibernate 中删除数据的几种方法
今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...
- NHibernate中使用memcache二级缓存
在NHibernate中使用memcache二级缓存 一.Windows下安装Memcache 1. 下载 http://jehiah.cz/projects/memcached-win32/ ...
- (转)Spring中Singleton模式的线程安全
不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...
随机推荐
- 通俗理解word2vec
https://www.jianshu.com/p/471d9bfbd72f 独热编码 独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有 ...
- WIN10平板 传递优化文件能否删除
在给系统准备做Ghost备份之前,一般会运行一次磁盘清理,但是WIN10系统多了一个传递优化文件(现在看到的体积很小,但其实可能是4-5G) 这个文件只是WIN10改进了系统更新策略产生的,就像是BT ...
- postgresql 窗口函数排序实例
经常遇到一种应用场景,将部分行的内容进行汇总.比较.排序. 比如数据表名称test.test2 select num,province from test.test2 得到结果: ;"黑龙江 ...
- mysqld_safe 无法启动的原因
[root@localhost ~]# 170408 09:53:13 mysqld_safe Logging to '/usr/local/mysql/data/localhost.localdom ...
- PHP——自定义比较算法
很多时候,程序都是直接写好逻辑运算,提供给用户的是一个值,然后后台去比较:但是有时会提供一种类似计算器一样的交互方式的时候,PHP只能读懂用户的输入来进行比较了- 最近的一个项目涉及到一个由用户自定义 ...
- Android 网络知识必知必会
目录: 网络分层 TCP 和 UDP 区别 TCP 三次握手以及为什么需要三次握手 UDP 四次挥手以及为什么需要四次挥手 socket 开发相关 Http 是什么 Https 是什么以及和 HTTP ...
- Spring Boot 2.0 热部署指南
Spring Boot 2.0 支持热部署,实现方法很简单 Spring Boot 2.0 有几种热重载的选项. 推荐的方法是使用spring-boot-devtools 因为它提供了额外的开发时间功 ...
- 译 5. Spring使用JDBC访问关系数据
本指南将引导您完成使用Spring访问关系数据的过程.原文阅读 1. 你将构建什么? 您将使用Spring的JdbcTemplate构建一个应用程序来访问存储在关系数据库中的数据. 2. 你需要准备什 ...
- 手动下载python更新后 换回以前版本
因为用的时Ubuntu略低版本的,不想更新版本,但是经常更新内核和其他软件,尤其是最近自己更新python,但是软件更新救出错了,而且不能打开“Languae Support”(软件支持)和ibus输 ...
- 提一下InfoQ
昨天在微信读书中整理了一个"架构师"清单,把InfoQ中文社区这两年发布的电子书整理到了一起,分享给了团队成员. 如果你去研究InfoQ中文社区,就会发现其中一个人与之因缘际会的相 ...