我现在正陷入NHibernate,我正在努力找出如何最好地正确设计我的存储库,同时正确管理会话的生命周期。
从我看过的例子中,通常的做法是将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时,我们应该始终将我们的调用包装在一个Transaction中 - 如果事务发生故障,那么我们必须回滚事务并关闭Session。
在这两种情况下,存储库都会在引用已关闭的会话时失效。
我的特定应用程序是一个长时间运行的过程,只会偶尔调用NHibernate,所以我希望会有很高的周转率,而不是在应用程序的生命周期内保持1个会话开放。
因此,我想知道处理这种特殊情况的既定模式是什么?我看到了几种可能的解决方案,但很难看出哪种解决方案最佳:
1)每次进程需要进行一些数据库工作时,重建存储库(并创建一个新的Session)。
2)使用SessionFactory注入存储库。然后,存储库公开此SessionFactory。然后,每个存储库的使用者在开始事务的同时打开一个新的会话。
3)创建一个UnitOfWork类,它被注入到存储库中,负责管理会话生存期和时间。交易。每次调用存储库时,都会调用UnitOfWork,它会创建一个全新的Session,并在Transaction中执行调用。因此,存储库不了解会话/事务。
对我而言,3)似乎是最好的解决方案,我在网上看到了一些这样的例子,但在所有的例子中,他们只在UnitOfWork中创建了1个会话,如果交易他们不会重新创建它回滚。
此外,3)的限制是UnitOfWork与特定存储库绑定,因此您无法拥有调用不同存储库的事务。
希望这是有道理的,并希望得到任何指导。
由于
答案 0 :(得分: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容器的强大功能来管理会话生命周期。
如果您对最后一个选项感兴趣,我可以向您展示一个示例。