使用Autofac管理NHibernate的ISession

18

有没有关于如何使用Autofac来管理NHibernate ISession实例(在ASP.NET MVC应用程序中)的提示或最佳实践?

2个回答

21

我对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<>而不是直接请求类型来获得这种控制。如果不使用Func<>,则需要在控制器实例创建之前预先创建会话实例。

接下来,Autofac的默认设置是实例的生命周期与其容器相同。由于我们知道需要在工作单元完成后立即处理此实例,因此我们请求一个Owned实例。在这种情况下,处理拥有的实例将立即处理底层会话。


3
嗯...我希望人们在踩票时能给一些有建设性的批评意见。 - Peter Lillevold
2
使用 InstancePerHttpRequest 替代 Func<Owned<>>,对于 ISession 对象来说是一个可选方案。我相信它是 Autofac.Integration.Mvc 的一部分(使用 nuget)。 - Chris Klepeis
@ChrisKlepeis - 是的,如果你的工作单元与请求的范围匹配,那么你可以这样做。这通常是情况,但并非总是如此。 - Peter Lillevold
这种方法与仅将ISessionFactory保留在容器中并根据需要执行Resolve().OpenSession()相比有何优势?它的工作方式相同,不需要将接口与Autofac类(如“Owned”)耦合。 - KT.
我也不确定为什么在这里需要一个Owned<ISession>。我们是自己创建它,而不是通过容器。容器为什么会关心它呢? - KT.
显示剩余3条评论

0

编辑:听起来像是Autofac以及其他容器可以正确地控制生命周期。如果是这样的话,请继续使用。

直接使用IoC容器管理会话并不是一个好主意。您的会话生命周期应该对应于工作单元(事务边界)。在Web应用程序的情况下,几乎肯定应该是Web请求的生命周期。

最常见的方法是使用HttpModule,在请求开始时创建会话并启动事务,然后在请求完成时提交。我建议HttpModule将会话注册到HttpContext.Items集合中。

在您的IoC容器中,可以注册类似于HttpContextSessionLocator的ISessionLocator。

我应该提到,您的通用错误处理应该定位当前会话并自动回滚事务,否则您可能会提交一半的工作单元。


1
我同意詹姆斯的观点,我在我的(asp.net mvc)控制器中注入了一个工作单元工厂,并在需要时从控制器内部创建一个工作单元。该工厂只是IoC容器(Structure Map)的包装类(服务定位器)。 - AwkwardCoder
@AWC:这正是我也会做的事情。问题在于,Autofac容器可以为你提供OOTB的工厂功能。 - Peter Lillevold
1
嗨詹姆斯,我相信AutoFac提供了HttpRequestScoped(),我认为它将提供与http模块相同的行为。我可能错了,但我认为其中一个好处是它只会在实际使用它的请求中创建新对象,而不是在所有请求中都创建,就像使用HttpModule一样。 - UpTheCreek
谢谢你提供的有关通用错误处理和回滚的提示 - 我会记住的! - UpTheCreek
1
@UpTheCreek。有趣的是,我以前从未使用过Autofac。听起来好像会起作用,只要它为您调用Dispose。 - James L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接