前言
1、本文以mvc3为例,借鉴开源项目 NerdDnner项目完成nhibernate中的 Session-per-request 模式,本文创建了一个自定义的httpmodel类,来实现在http请求的时候创建并开启一个session并绑定到CurrentSessionContext中,当请求完成以后关闭,同时包含对事物的处理。
2、利用MiniProfiler.NHibernate来追踪项目中的产生的sql,便于我们及时发现问题及时处理。MiniProfiler.NHibernate现在可以在nuget上直接获取或者可以去github中下载源码查看。
实现Session per request
public class NHibernateSessionPerRequest : IHttpModule { private static readonly ISessionFactory sessionFactory; //构造函数 static NHibernateSessionPerRequest() { sessionFactory = CreateSessionFactory(); } // 初始化httpmodel public void Init( HttpApplication context ) { context.BeginRequest += BeginRequest; context.EndRequest += EndRequest; } public void Dispose() { } public static ISession GetCurrentSession() { return sessionFactory.GetCurrentSession(); } // 打开session, 开启事务, 绑定session到CurrentSessionContext private static void BeginRequest( object sender, EventArgs e ) { ISession session = sessionFactory.OpenSession(); session.BeginTransaction(); CurrentSessionContext.Bind( session ); } // 移除session会话, 事物提交, and 关闭session会话 private static void EndRequest( object sender, EventArgs e ) { ISession session = CurrentSessionContext.Unbind( sessionFactory ); if ( session == null ) return; try { session.Transaction.Commit(); } catch ( Exception ) { session.Transaction.Rollback(); } finally { session.Close(); session.Dispose(); } } // 创建sessionfactory private static ISessionFactory CreateSessionFactory() { return Fluently.Configure(new Configuration().Configure()) .Mappings( m => m.AutoMappings.Add( CreateMappings() ) ) .ExposeConfiguration( UpdateSchema ) .CurrentSessionContext<WebSessionContext>() .BuildSessionFactory(); } private static AutoPersistenceModel CreateMappings() { return AutoMap .Assembly( System.Reflection.Assembly.GetCallingAssembly() ) .Where( t => t.Namespace != null && t.Namespace.EndsWith( "Models" ) ) .Conventions.Setup( c => c.Add( DefaultCascade.SaveUpdate() ) ); } // 生成数据库架构 private static void UpdateSchema( Configuration cfg ) { new SchemaUpdate( cfg ) .Execute( false, true ); } }
此类的nh的配置采用fluent的方式配置映射,可以生成数据库架构,ISessionFactory在每次请求中只会生成一次,当我们需要session的时候只需调用GetCurrentSession方法,当http请求的时候session创建并存储在CurrentSessionContext.Bind()中,并开启事物操作,当请求结束的时候 CurrentSessionContext.Unbind()移除session,事物提交并将session关闭。这里存在一些问题:尽管session是非常轻量级的,这样每一次http请求都会去创建session,并不能做到我们真正需要的时候去创建。
注册httpmodel:
在web.config中添加如下2处节点:
测试程序
Models:
public class Employee { public virtual int Id { get; protected set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } public virtual Store Store { get; set; } } public class Product { public virtual int Id { get; protected set; } public virtual string Name { get; set; } public virtual double Price { get; set; } public virtual IList<Store> StoresStockedIn { get; protected set; } public Product() { StoresStockedIn = new List<Store>(); } } public class Store { public virtual int Id { get; protected set; } public virtual string Name { get; set; } public virtual IList<Product> Products { get; protected set; } public virtual IList<Employee> Staff { get; protected set; } public Store() { Products = new List<Product>(); Staff = new List<Employee>(); } public virtual void AddProduct( Product product ) { product.StoresStockedIn.Add( this ); Products.Add( product ); } public virtual void AddEmployee( Employee employee ) { employee.Store = this; Staff.Add( employee ); } }