• 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管理的类。

      1 using NHibernate;
      2 using NHibernate.Cfg;
      3 using NHibernate.Context;
      4 using System;
      5 using System.Web;
      6 
      7 namespace Demo.Service
      8 {
      9     /// <summary>
     10     /// Manages the NHibernate session
     11     /// </summary>
     12     public class SessionManager
     13     {
     14         private static ISessionFactory SessionFactory { get; set; }
     15 
     16         public static string ConnectionString { get; set; }
     17 
     18         private static ISessionFactory GetFactory<T>() where T : ICurrentSessionContext
     19         {
     20             var cfg = new Configuration();
     21 
     22             cfg.DataBaseIntegration(x => {
     23 #if DEBUG
     24                 x.LogSqlInConsole = true;
     25 #endif
     26                 if (!string.IsNullOrEmpty(ConnectionString)
     27                     && ConnectionString.Trim() != "")
     28                 {
     29                     x.ConnectionString = ConnectionString;
     30                 }
     31             });
     32 
     33             cfg.Configure().CurrentSessionContext<T>();
     34             return cfg.BuildSessionFactory();
     35         }
     36 
     37         /// <summary>
     38         /// Gets the current session.
     39         /// </summary>
     40         public static ISession GetCurrentSession()
     41         {
     42             if (SessionFactory == null)
     43             {
     44                 SessionFactory = HttpContext.Current != null ? GetFactory<WebSessionContext>() : GetFactory<ThreadStaticSessionContext>();
     45             }
     46 
     47             if (CurrentSessionContext.HasBind(SessionFactory))
     48             {
     49                 return SessionFactory.GetCurrentSession();
     50             }
     51 
     52             var session = SessionFactory.OpenSession();
     53             CurrentSessionContext.Bind(session);
     54 
     55             return session;
     56         }
     57 
     58         /// <summary>
     59         /// Closes the session.
     60         /// </summary>
     61         public static void CloseSession()
     62         {
     63             if (SessionFactory != null && CurrentSessionContext.HasBind(SessionFactory))
     64             {
     65                 var session = CurrentSessionContext.Unbind(SessionFactory);
     66                 if (session != null && session.IsOpen)
     67                 {
     68                     session.Close();
     69                 }
     70             }
     71         }

    2. 在Asp.Net程序中管理ISession对象

    Asp.Net的页面请求过程是无状态的,不能将ISession对象持久化到内存中。但是可以使用自定义的IHttpModule对象来实现:每生成一个HTTP请求,生成一个ISession。

     1     public class SessionModule : IHttpModule
     2     {
     3         public void Init(HttpApplication context)
     4         {
     5             context.EndRequest += (sender, e) => SessionManager.CloseSession();
     6         }
     7 
     8         public void Dispose()
     9         {
    10         }
    11     }

    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条件。

     1 using System.Collections.Generic;
     2 using System.Linq;
     3 
     4 namespace Demo.Service.Infrastructure.Interface
     5 {
     6     public interface IService<T> where T : class
     7     {
     8         IList<T> GetAll();
     9         IQueryable<T> Query();
    10         T GetById(int id);
    11         T LoadById(int id);
    12         int Save(T obj, bool includeInTransaction = false);
    13         void Update(T obj, bool includeInTransaction = false);
    14         void Delete(int id, bool includeInTransaction = false);
    15     }
    16 }

    定义实现类Service<T>

     1 using Demo.Service.Infrastructure.Interface;
     2 using NHibernate;
     3 using NHibernate.Linq;
     4 using System;
     5 using System.Collections.Generic;
     6 using System.Linq;
     7 
     8 namespace Demo.Service.Infrastructure
     9 {
    10     public class Service<T> : IService<T> where T : class
    11     {
    12         protected ISession Session
    13         {
    14             get { return SessionManager.GetCurrentSession(); }
    15         }
    16 
    17         public IList<T> GetAll()
    18         {
    19             IList<T> list = Session.CreateCriteria<T>().List<T>();
    20             return list;
    21         }
    22 
    23         public virtual IQueryable<T> Query()
    24         {
    25             var result = Session.Query<T>();
    26             return result;
    27         }
    28 
    29         public T GetById(int id)
    30         {
    31             T obj = Session.Get<T>(id);
    32             return obj;
    33         }
    34 
    35         public T LoadById(int id)
    36         {
    37             T obj = Session.Load<T>(id);
    38             return obj;
    39         }
    40 
    41         public int Save(T obj, bool includeInTransaction = false)
    42         {
    43             var identifier = Session.Save(obj);
    44             if (!includeInTransaction)
    45             {
    46                 Session.Flush();
    47             }
    48             return Convert.ToInt32(identifier);
    49         }
    50 
    51         public void Update(T obj, bool includeInTransaction = false)
    52         {
    53             Session.SaveOrUpdate(obj);
    54             if (!includeInTransaction)
    55             {
    56                 Session.Flush();
    57             }
    58         }
    59 
    60         public void Delete(int id, bool includeInTransaction = false)
    61         {
    62             var obj = Session.Get<T>(id);
    63             Session.Delete(obj);
    64             if (!includeInTransaction)
    65             {
    66                 Session.Flush();
    67             }
    68         }
    69     }
    70 }

    在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的关系映射。

  • 相关阅读:
    Python程序执行时的不同电脑路径不同问题
    Python写的计算器程序(主要目的在于熟悉下正则表达式)
    占位符
    selenium自动化测试浏览器驱动安装(属于转载文章)
    python的pip升级问题
    索引
    视图
    事务
    引擎
    约束
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/5656024.html
Copyright © 2020-2023  润新知