【问题标题】:How to manage NHibernate sessions when using Repositories/Transactions使用存储库/事务时如何管理 NHibernate 会话
【发布时间】:2015-06-20 09:40:13
【问题描述】:

我现在陷入了 NHibernate,我正在尝试找出如何最好地正确设计我的存储库,同时正确管理 Session 的生命周期。

从我看到的示例来看,将 ISession 注入每个存储库中似乎很常见,如下所示:

public class SomeRepository : IRepository
{
    private readonly ISession _session;

    public SomeRepository(ISession session)
    {
        _session = session;
    }

    public IList<T> LoadSomeData()
    {
        return _session.Query<T>().Where(...).ToList();
    }
}

所以这很好,但我可以看到一些会出现问题的情况:

1) 在应用的生命周期内可能没有 1 个会话。

2) 当访问 NHibernate 时,我们应该始终将我们的调用包装在一个事务中 - 如果事务出错,那么我们必须回滚事务并关闭会话。

在这两种情况下,存储库都将失效,因为它引用了一个关闭的会话。

我的特定应用程序是一个长时间运行的进程,它只会偶尔调用 NHibernate,所以我希望 Sessions 的周转率很高,而不是在应用程序的整个生命周期内保持 1 个 Session 处于打开状态。

因此,我想知道处理这种特殊情况的既定模式是什么?我看到了几个潜在的解决方案,但很难看出哪个是最佳做法:

1) 每次进程需要执行一些数据库工作时,重新构建存储库(并创建一个新会话)。

2) 使用 SessionFactory 注入存储库。然后存储库公开这个 SessionFactory。然后每个存储库的消费者在启动事务的同时打开一个新会话。

3) 创建一个 UnitOfWork 类,该类被注入存储库并负责管理会话生命周期和事务。每次调用 Repository 时,都会调用 UnitOfWork,它会创建一个全新的 Session 并在 Transaction 中执行调用。因此,存储库不知道会话/事务。

对我来说,3) 似乎是最好的解决方案,我在网上看到了一些这样的例子,但在所有例子中,他们只在 UnitOfWork 中创建了 1 个会话,并且如果交易他们不会重新创建它被回滚。

此外,3) 的限制是 UnitOfWork 与特定存储库相关联,因此您不能拥有调用不同存储库的事务。

希望这是有道理的,并希望得到任何指导。

谢谢

【问题讨论】:

    标签: c# nhibernate unit-of-work


    【解决方案1】:

    实际上NHibernate中的Session可以作为UnitOfWork使用。但是如果你想使用这种模式,这里是实现:http://nhibernate.info/doc/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.html

    但是,您列表中的最佳解决方案是 1。因此,您需要在每次需要使用 DB 完成工作时创建会话和存储库。

    使用 UnitOfWork 它看起来像:

    using(var uow = new UnitOfWork())
    {
       var rep1 = new SomeRepository1(uow);
       rep1.DoSomeJob();
    
       var rep2 = new SomeRepository2(uow);
       rep2.DoSomeOtherJob();
    }
    

    使用原生 ISession:

    using(var session = SessionFactory.OpenSession())
    using(var tr = session.BeginTransaction())
    {
       var rep1 = new SomeRepository1(session);
       rep1.DoSomeJob();
    
       var rep2 = new SomeRepository2(session);
       rep2.DoSomeOtherJob();
    
       tr.Commit();
    }
    

    您还可以利用 DI/IoC 容器的强大功能来管理会话的生命周期。

    如果您对最后一个选项感兴趣,我可以向您展示一个示例。

    【讨论】:

    • 感谢您的回复,我最终明白了这一点,并采用了与您发布的内容类似的内容,从而创建了一个新的 UnitOfWork,它负责打开一个新会话并管理事务.然后使用来自此 UnitOfWork 的会话来构建存储库。一旦关闭会话的事务提交,UoW 就会被释放。
    • 好。但在我的应用程序中,我采用了另一种方式: 1. 我实现了管理嵌套事务的业务事务。 2. 我使用 [en.wikipedia.org/wiki/Active_record_pattern] (ActiveRecord) 模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    相关资源
    最近更新 更多