我正在使用 NHibernate 3 开始一个新项目,并且正在尝试将 CurrentSessionContext API 与 WebSessionContext 一起使用来管理我的 ISession 对象。
在以前的项目中,我总是自己管理,所以每当我需要一个 ISession 对象时,我都会创建它并存储在 HttpContext.Items 集合中。非常简单,但使用本机解决方案 (CurrentSessionContext) 似乎是这个新项目的最佳选择。
当我管理对象时,我能够对其进行延迟初始化,这意味着我只会在需要时打开一个会话,而不是在每个请求中打开它,因为我可能不需要它,并且打开它会浪费资源/时间时间。
有没有一种简单的方法可以使用 CurrentSessionContext API 做到这一点?
这是我在负责此操作的 HttpModule 中使用的代码:
public class ContextualSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private static void context_BeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
BindSession(context);
}
private static void BindSession(HttpContext context)
{
// Create a new session (it's the beginning of the request)
var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();
// Tell NH session context to use it
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
UnbindSession(context);
}
private static void UnbindSession(HttpContext context)
{
// Get the default NH session factory
var factory = SessionBuilderFactory.CurrentSessionFactory;
// Give it to NH so it can pull the right session
var session = CurrentSessionContext.Unbind(factory);
if (session == null) return;
session.Flush();
session.Close();
}
}
编辑
Diego 几乎做到了,但我对此进行了更多思考,我记得我自己实现该控制的主要原因:事务。
我是洋葱架构师,所以我的域对象(知道何时开始事务的对象)无法访问基础设施,因此他们无法开始事务。
为了解决这个问题,我使用延迟初始化,并且总是在打开 Session 时启动事务。当请求结束并且没有捕获到异常时,就会发生提交。除此之外,Ayende 的建议是始终使用事务,即使在查询时也是如此。有什么想法吗?