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的处理 线程不安全的更多相关文章

  1. Hibernate中Session与本地线程绑定

    ------------------siwuxie095 Hibernate 中 Session 与本地线程绑定 1.Session 类似于 JDBC 的连接 Connection 2.Session ...

  2. NHibernate中session.update()及session.merge()的区别

    今天的工作中遇到一个奇怪的问题,如下: "a different object with the same identifier value was already associated w ...

  3. NHibernate中的API

    本篇文章介绍的是NHibernate的各种API及其作用. 下图描述了NHibernate的API在分层架构中的作用,下面将进行详细说明. NHibernate的接口大致分为四类:1.  被应用程序调 ...

  4. NHibernate中,查询SqlServer数据库多个实体对象

    关于datetime类型使用:  Oracle:  "and tb.EffectiveDate >= to_date(?,'yyyy-mm')" Sql:  "an ...

  5. NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  6. hibernate中session的获取使用以及其他注意事项

    hibernate中session的获取使用以及其他注意事项 前言:工作时,在同时使用Hibernate的getSession().getHibernateTemplate()获取Session后进行 ...

  7. 总结NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  8. NHibernate中使用memcache二级缓存

    在NHibernate中使用memcache二级缓存 一.Windows下安装Memcache  1. 下载   http://jehiah.cz/projects/memcached-win32/  ...

  9. (转)Spring中Singleton模式的线程安全

    不知道哪里的文章,总结性还是比较好的.但是代码凌乱,有的还没有图.如果找到原文了可以进行替换! spring中的单例 spring中管理的bean实例默认情况下是单例的[sigleton类型],就还有 ...

随机推荐

  1. Markdown 语法手册 - 完整版(上)

    https://blog.csdn.net/witnessai1/article/details/52551362 1. 斜体和粗体 代码: *斜体*或_斜体_ **粗体** ***加粗斜体*** ~ ...

  2. 9.4 dubbo异步调用原理

    9.1 客户端发起请求源码.9.2 服务端接收请求消息并发送响应消息源码.9.3 客户端接收响应信息(异步转同步的实现) 分析了dubbo同步调用的源码,现在来看一下dubbo异步调用. 一.使用方式 ...

  3. 关于VC预定义常量_WIN32,WIN32,_WIN64(转)

    VC2012 下写 Windows 程序时,有时需要判断编译环境.在之前的文章<判断程序是否运行在 Windows x64 系统下.>里说过如何在运行期间判断系统环境,但在编译时如何判断? ...

  4. 解决IE6-IE8 Js代码不执行问题

    一种可能的原因:form标签不完整. 使用在线工具,测试html代码标签的完整性.

  5. awesomes前端资源库网站

    https://www.awesomes.cn http://www.cnblogs.com/jiujiaoyangkang/p/4998518.html (web app自适应框架flexible) ...

  6. 一道笔试题:给定编码规则,实现decode()方法

    public class CodeDecode {     /*变换函数encode()顺序考察已知字符串的字符,按以下规则逐组生成新字符串:       (1)若已知字符串的当前字符不是大于0的数字 ...

  7. swift3 与 OC 语法区别

    1.Swift还增加了Objective-C中没有的类型比如元组(Tuple). 元组可以让你创建或者传递一组数据,比如作为函数的返回值时,你可以用一个元组可以返回多个值. 元组(tuples)把多个 ...

  8. Linux使用过程中常见问题及其解决方法

    “我不怕问题的出现,相反,我喜欢问题,因为我知道这是一种成长............” 1,ubuntu中文输入法的安装:  今天重装了英文版的ubuntu,而发现中文输入法并没有自动安装好,于是搜了 ...

  9. 将R非时间序列的data.frame转变为时序格式

    将R非时间序列的data.frame转变为时序格式,常常会用到,尤其是股票数据处理中, 举例:dailyData包括两列数据:Date Close10/11/2013 871.9910/10/2013 ...

  10. 在 word 中对正文和目录进行分节显示页码

    使用版本 word 2016 使目录独占一页:在正文第一页的第一个字符前插入分节符下一页(布局--分节符--下一页),此时会在正文第一个字符前插入分节符.在之前插入一张空白页,用于插入目录.(插入 - ...