Sessions and Transactions
会话和事务
简介
NHibernate让应用程序来处理会话和事务管理. 有几种不同的方法来处理会话和事务管理, 这些方法很大程度上依赖具体的应用程序架构.除了一些有趣的会话方法 , 本章还介绍:针对不同类型的应用程序如何处理会话和事务.
Setting up session per web request
session-per-request模式构建会话
出于简单性的考虑,在web应用程序中管理NHibernate会话的最常见的模式就是session-per-request. 本节介绍如何使用NHibernate的上下文会话特性来构建该模式.
准备
1. 创建一个ASP.NET Web Forms或ASP.NET MVC 应用程序.
2. 添加引用:NHibernate.dll, NHibernate.ByteCode.Castle.dll, log4net.dll, 和Eg.Core项目.
3. 在web.config文件中, 创建NHibernate和log4net配置节点. 可以参考第二章中Configuring NHibernate with App.config小节的示例.
步骤
1. 在web.config中的hibernate-configuration节点,添加current_session_context_class属性并将其值设置为web .
2. 添加一个Global application类(Global.asax),如果他不存在的话.
3. 在Global.asax中, 添加下述using语句:
using NHibernate; using NHibernate.Cfg; using NHibernate.Context;
4. 创建一个名为SessionFactory的静态属性:
public static ISessionFactory SessionFactory { get; private set; }
5. 在Application_Start方法中,添加下述代码:
protected void Application_Start(object sender, EventArgs e) { log4net.Config.XmlConfigurator.Configure(); var nhConfig = new Configuration().Configure(); SessionFactory = nhConfig.BuildSessionFactory(); }
6. 在Application_BeginRequest方法中, 添加下述代码:
protected void Application_BeginRequest(object sender, EventArgs e) { var session = SessionFactory.OpenSession(); CurrentSessionContext.Bind(session); }
7. 在Application_EndRequest方法中, 添加下述代码:
protected void Application_EndRequest(object sender, EventArgs e) { var session = CurrentSessionContext.Unbind(SessionFactory); session.Dispose(); }
原理
在web应用程序中,每个web请求使用一个会话是很常见的. 在请求开始时打开会话并在请求结束时关闭会话.NHibernate的上下文会话特性使得一个会话关联一些特定的应用程序域,类似于一个单一的工作单元. 使用current_session_context_class属性来配置该上下文,该属性指定了NHibernate.Context.ICurrentSessionContext的一个实现. 示例中我们将她喝web请求相关联. 此处web是NHibernate.Context.WebSessionContext的缩写名.在上下文会话中,NHibernate也不会打开,关闭,注销我们的会话. 而使用当前的web请求来关联和分离会话,具体是使用:CurrentSessionContext.Bind和Unbind方法.
扩展
使用SessionFactory.GetCurrentSession()来为当前web请求获得NHibernate会话.在我们的web应用程序示例中,代码如下:
Guid productId = new Guid(Request["id"]); Eg.Core.Product product; var session = Global.SessionFactory.GetCurrentSession(); using (var tran = session.BeginTransaction()) { product = session.Get<Eg.Core.Product>(productId); tran.Commit(); } Page.Title = product.Name; Label1.Text = product.Name; Label2.Text = product.Description;
在这个尚不成熟的示例中从数据库中抓取一个产品并将她的名字和描述展示给用户.在实际应用中我们使用依赖注入来替代对单例模式的直接访问.TekPub Concepts上提供了一个深入介绍依赖注入的免费视频,网址为: http://tekpub.com/view/concepts/1.
提示
NHibernate会话是相当的轻量级并且使用的开销很小. 只打开一个会话的并不会打开一个数据库连接. NHibernate会尽量避免打开连接的延迟. 另一方面, NHibernate在创建会话工厂时开销很大. 所以在整个应用程序生命期中应该只创建一个会话工厂.
有很多使用控制反转容器甚至HTTP模块去达成session per request模式的实现. 其中的一些使用上下文会话. 其他的一些也没有使用NHibernate来管理会话.一个完全的session per request实现会有4个特征:
- 应用程序开始运行后只创建一个会话工厂.
- 有web请求时会打开一个会话.
- 请求结束时关闭该会话.
- 提供一种标准的方式来访问当前会话的整个数据访问层.