有没有人有关于Autofac如何帮助管理NHibernate ISession实例的任何提示或最佳实践(在ASP.NET MVC应用程序的情况下)?
答案 0 :(得分:19)
我不太熟悉如何处理NHibernate会话。也就是说,Autofac具有出色的实例生命周期处理能力(scoping和deterministic disposal)。一些相关资源是this article和this question。由于你在ASP.Net MVC的土地上,请确保你也查看the MVC integration stuff。
为了说明这一点,下面是一个快速示例,说明如何使用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());
更新:我的理由是,根据this NHibernate tutorial,会话实例的生命周期应该是“工作单元”的生命周期。因此,我们需要一些方法来控制创建会话实例和处理会话的时间。
使用Autofac,我们通过直接请求Func<>
而不是类型来获得此控制。不使用Func<>
将要求在创建控制器实例之前预先创建会话实例。
接下来,Autofac中的默认值是实例具有其容器的生命周期。由于我们知道在完成工作单元后我们需要有权处理此实例,因此我们请求Owned
实例。在这种情况下,处置所拥有的实例将立即处置基础会话。
答案 1 :(得分:0)
编辑:听起来像Autofac,可能其他容器可以正确规定生命周期。如果是这样的话,那就去吧。
使用IoC容器直接管理会话并不是一个好主意。会话的生命周期应与您的工作单元(事务边界)相对应。对于Web应用程序,几乎可以肯定是Web请求的生命周期。
实现这一目标的最常见方法是使用HttpModule,它既可以创建会话,也可以在请求开始时启动事务,然后在请求完成时提交。我希望HttpModule在HttpContext.Items集合中注册会话。
在您的IoC容器中,您可以针对ISessionLocator注册类似HttpContextSessionLocator的内容。
我应该提一下,你的通用错误处理应该找到当前会话并自动回滚事务,否则你最终可能会提交半个工作单元。