关于 Autofac 如何帮助管理 NHibernate ISession 实例(对于 ASP.NET MVC 应用程序),是否有人有任何提示或最佳实践?
2 回答
我不太熟悉应该如何处理 NHibernate 会话。也就是说,Autofac 具有出色的实例生命周期处理(范围和确定性处理)。一些相关资源是这篇文章和这个问题。由于您在 ASP.Net MVC 领域,请确保您还研究了 MVC 集成的东西。
为了说明这一点,这里有一个关于如何使用 Autofac 工厂委托和Owned
泛型来完全控制实例生命周期的快速示例:
public class SomeController
{
private readonly Func<Owned<ISession>> _sessionFactory;
public SomeController(Func<Owned<ISession>> sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void DoSomeWork()
{
using (var session = _sessionFactory())
{
var transaction = session.Value.BeginTransaction();
....
}
}
}
使其工作的容器设置非常简单。请注意,我们不需要做任何事情来获取Func<>
和Owned<>
类型,这些是由 Autofac 自动提供的:
builder.Register(c => cfg.BuildSessionFactory())
.As<ISessionFactory>()
.SingleInstance();
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession());
更新:我的理由是,根据这个 NHibernate 教程,会话实例的生命周期应该是“工作单元”的生命周期。因此,我们需要某种方式来控制会话实例的创建时间和会话的释放时间。
使用 Autofac,我们通过Func<>
直接请求 a 而不是类型来获得这种控制。不使用Func<>
将要求在创建控制器实例之前预先创建会话实例。
接下来,Autofac 中的默认设置是实例具有其容器的生命周期。因为我们知道一旦工作单元完成我们需要处理这个实例的能力,我们请求一个Owned
实例。在这种情况下,处置拥有的实例将立即处置基础会话。
编辑:听起来像 Autofac 和可能其他容器可以正确地确定生命周期。如果是这样,那就去吧。
使用 IoC 容器直接管理会话不是一个好主意。会话的生命周期应与您的工作单元(事务边界)相对应。对于 Web 应用程序,这几乎可以肯定是 Web 请求的生命周期。
实现这一点的最常见方法是使用 HttpModule 来创建会话并在请求开始时启动事务,然后在请求完成时提交。我会让 HttpModule 在 HttpContext.Items 集合中注册会话。
在您的 IoC 容器中,您可以针对 ISessionLocator 注册类似 HttpContextSessionLocator 的内容。
我应该提到,您的通用错误处理应该定位当前会话并自动回滚事务,否则您最终可能会提交半个工作单元。