关键还是会话工厂的建立和NHibernate的Session的管理问题。
会话工厂仍然是使用singleton模式建立。而session管理则和Wndows Form不同:Wndows Form可以保持长连接,以获得比较好的用户体验,因而可以使用ThreadStaticAttribute或者TLS来保存session;在Web Form中使用ThreadStaticAttribute则不会如期望的那样工作,当有多个线程的时候,ThreadStaticAttribute的变量被第一个线程初始化后,其它的线程访问到的都是null,而每个HttpRequest则可能有多个线程为其服务,因而有人称ThreadStatic is evil,对于此,可以参考这个Blog。考虑到上述原因,在Web Form中使用TLS和ThreadStatic属性是不合适的,好的做法是使用HttpContext.Current.Items来共享session。我们使用HttpModule来处理之,下面是一个例子:
using System;
using System.Web;
using DAL;
using NHibernate;
namespace NHTest
{
/// <summary>
/// NHSessionModule 的摘要说明。
/// </summary>
public class NHSessionModule : IHttpModule
{
/// <summary>
/// Default constructor.
/// </summary>
public NHSessionModule()
{}
private IEntityManager manager = null;
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Context_BeginRequest);
context.EndRequest += new EventHandler(Context_EndRequest);
}
public void Dispose()
{
}
private void Context_BeginRequest(object sender, EventArgs e)
{
manager = EntityManager.CreateEntityManager();
ISession session = manager.Session as ISession;
HttpContext.Current.Items.Add("NHSession", session);
HttpContext.Current.Items.Add("Manager",manager);
}
private void Context_EndRequest(object sender, EventArgs e)
{
// Close the NHibernate session.
if ( HttpContext.Current.Items["NHSession"] != null )
{
ISession session = HttpContext.Current.Items["NHSession"] as ISession;
if ( session != null && session.IsOpen )
{
session.Close();
}
}
}
}
}
using System.Web;
using DAL;
using NHibernate;
namespace NHTest
{
/// <summary>
/// NHSessionModule 的摘要说明。
/// </summary>
public class NHSessionModule : IHttpModule
{
/// <summary>
/// Default constructor.
/// </summary>
public NHSessionModule()
{}
private IEntityManager manager = null;
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Context_BeginRequest);
context.EndRequest += new EventHandler(Context_EndRequest);
}
public void Dispose()
{
}
private void Context_BeginRequest(object sender, EventArgs e)
{
manager = EntityManager.CreateEntityManager();
ISession session = manager.Session as ISession;
HttpContext.Current.Items.Add("NHSession", session);
HttpContext.Current.Items.Add("Manager",manager);
}
private void Context_EndRequest(object sender, EventArgs e)
{
// Close the NHibernate session.
if ( HttpContext.Current.Items["NHSession"] != null )
{
ISession session = HttpContext.Current.Items["NHSession"] as ISession;
if ( session != null && session.IsOpen )
{
session.Close();
}
}
}
}
}
XML配置文件:
<system.web>
<httpModules>
<add type="NHTest.NHSessionModule,NHTest" name="NHSessionModule" />
</httpModules>
</system.web>
<httpModules>
<add type="NHTest.NHSessionModule,NHTest" name="NHSessionModule" />
</httpModules>
</system.web>
上面代码中的IEntityManager 是用来执行持久化以及查询的工具类(调用NHibernate中ISession提供的方法),然后在页面中先写一个页面基类来进行Session的获取:
using System;
using System.Web;
using System.Web.UI;
using DAL;
using NHibernate;
namespace NHTest
{
/// <summary>
/// BasePage 的摘要说明。
/// </summary>
public class BasePage : Page
{
private ISession _activeSession = null;
private IEntityManager _manager = null;
public BasePage()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public ISession ActiveSession
{
get { return this._activeSession; }
}
public IEntityManager Manager
{
get { return this._manager; }
}
protected override void OnInit(EventArgs e)
{
this._activeSession = HttpContext.Current.Items["NHSession"] as ISession;
this._manager = HttpContext.Current.Items["Manager"] as IEntityManager;
base.OnInit(e);
}
}
}
using System.Web;
using System.Web.UI;
using DAL;
using NHibernate;
namespace NHTest
{
/// <summary>
/// BasePage 的摘要说明。
/// </summary>
public class BasePage : Page
{
private ISession _activeSession = null;
private IEntityManager _manager = null;
public BasePage()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public ISession ActiveSession
{
get { return this._activeSession; }
}
public IEntityManager Manager
{
get { return this._manager; }
}
protected override void OnInit(EventArgs e)
{
this._activeSession = HttpContext.Current.Items["NHSession"] as ISession;
this._manager = HttpContext.Current.Items["Manager"] as IEntityManager;
base.OnInit(e);
}
}
}
在页面中可以这么用:
private IEntityManager manager = null;
private ISession session = null;
private void Button1_Click(object sender, EventArgs e)
{
session = base.ActiveSession;
manager = base.Manager;
IList list = manager.GetList(session, typeof ( MyBusinessType));
DataGrid1.DataSource = list;
DataGrid1.DataBind();
}
private ISession session = null;
private void Button1_Click(object sender, EventArgs e)
{
session = base.ActiveSession;
manager = base.Manager;
IList list = manager.GetList(session, typeof ( MyBusinessType));
DataGrid1.DataSource = list;
DataGrid1.DataBind();
}