• 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();
            }

        }

  • 相关阅读:
    Velocity 创建命令缓存
    关于RESTful Web Services和RESTful设计的一些文章
    [转]Restful Web Services浅析
    Silverlight点滴(四)Silverlight访问Web Service报"System.Security.SecurityException: 安全性错误"的处理
    WebDevHelper RESTful服务和Ajax开发时的利器
    [原]读Google Data API源代码一:从创建一个日历(Calendar)开始
    [转]使用 WCF 和 .NET Framework 3.5 进行 HTTP 编程
    [原]Silverlight3 支持所有HTTP方法
    [原]RESTful Web Service之以HTTP PUT方式调用WCF服务
    [原]Google API学习2:Google API稍深入一步
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/4631412.html
Copyright © 2020-2023  润新知