我有以下实现,并希望获得一些关于它是否正确使用 NHibernate 进行 session 和事务的反馈。
public interface IUnitOfWork : IDisposable
{
ISession CurrentSession { get; }
void Commit();
void Rollback();
}
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
public ISession CurrentSession { get; private set; }
public void Dispose()
{
CurrentSession.Close();
CurrentSession = null;
}
public void Commit()
{
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive) _transaction.Rollback();
}
}
Ninject 绑定(bind)
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope();
Bind<IRepository>().To<Repository>().InTransientScope();
这是一个用法示例:
public class Repository : IRepository
{
private readonly ISessionFactory _sessionFactory;
public Repository(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void Add(IObj obj)
{
using (var unitOfWork = new UnitOfWork(_sessionFactory))
{
unitOfWork.CurrentSession.Save(obj);
unitOfWork.Commit();
}
}
}
在我之前的实现中,我会将 IUnitOfWork 注入(inject)到我的存储库构造函数中,如下所示
public Repository(IUnitOfWork unitOfWork)
{...
但是 Dispose() 方法不会执行,导致后续调用抛出此异常:“无法访问已处置的对象。对象名称:'AdoTransaction'。”
最佳答案
第一个观察结果:您的存储库不应提交工作单元。这违背了工作单元模式的全部要点。通过立即将更改保存到存储库中,您可以“微观管理”NHibernate session 。
工作单元应该在堆栈的更高层(应用程序/服务层)中引用。这允许您让应用程序代码执行多个操作(可能在不同的存储库上),并且最终仍然一次提交所有内容。
UnitOfWork 类本身看起来不错,但您应该问问自己是否真的需要它。在 NHibernate 中,ISession 是您的工作单元。您的 UnitOfWork 类似乎没有增加很多值(value)(特别是因为您无论如何都暴露了 CurrentSession 属性)
但你确实需要考虑它的生命周期。我认为你在这一点上是错误的。 session 生命周期管理取决于您正在开发的应用程序的类型:在 Web 应用程序中,您通常希望每个请求都有一个工作单元(您可能需要在 google 上搜索“每个请求的 nhibernate session ”)。在桌面应用程序中,情况稍微复杂一些,大多数时候您需要“每个屏幕 session ”或“每个业务交易对话”。
关于nhibernate - 正确使用NHibernate工作单元模式和Ninject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4271265/