Bri*_*n T 15 nhibernate session transactions ninject unit-of-work
我有以下实现,并希望得到一些反馈,以确定它是否正确使用NHibernate进行会话和事务.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Ninject绑定
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope();
Bind<IRepository>().To<Repository>().InTransientScope();
Run Code Online (Sandbox Code Playgroud)
以下是用法示例:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我之前的实现中,我会将IUnitOfWork注入到我的存储库构造函数中
public Repository(IUnitOfWork unitOfWork)
{...
Run Code Online (Sandbox Code Playgroud)
但Dispose()方法不会执行导致后续调用抛出此异常:"无法访问已处置的对象.对象名称:'AdoTransaction'."
jer*_*enh 35
首先观察:您的存储库不应该提交工作单元.这打破了工作单元模式的全部要点.通过立即将更改保存在存储库中,您可以"微观管理"NHibernate会话.
在应用程序/服务层中,应在堆栈的较高位置引用工作单元.这允许您拥有执行多个操作的应用程序代码,可能在不同的存储库上,并且最后仍然可以一次提交所有内容.
UnitOfWork类本身看起来很好,但你应该问自己是否真的需要它.在NHibernate中,ISession是您的工作单元.你的UnitOfWork类似乎没有增加很多价值(特别是因为你无论如何暴露了CurrentSession属性)
但你需要考虑它的寿命.我认为你在这一点上做错了.会话生命周期管理取决于您正在开发的应用程序类型:在Web应用程序中,您通常希望每个请求都有一个工作单元(您可能希望在每个请求的'nhibernate会话'上进行google).在桌面应用程序中,它稍微复杂一点,您大多数时候都想要"每个屏幕的会话"或"每个业务交易的对话".
我有一个主要的CRUD类型的应用程序,我实现了工作单元与存储库模式,但无法真正摆脱会话/事务分裂.会话和交易需要不同的生命周期.在桌面世界中,会话通常是"按屏幕",而事务是"按用户操作".
这篇优秀文章中的更多信息.
所以我最终得到的是:
IUnitOfWork
- >包装会话,实现 IDisposable
IAtomicUnitOfWork
- >包装事务,实现 IDisposable
IRepository
- >提供获取,保存,删除和查询访问权限我这样做是为了你需要一个IUnitOfWork
构建一个IAtomicUnitOfWork
,你需要一个IAtomicUnitOfWork
构建一个IRepository
,以便执行适当的事务管理.这实际上是我通过实现自己的接口获得的.
正如jeroenh所说,你几乎可以使用ISession
,ITransaction
但最后我觉得在我定义的界面上编写所有代码要好一些.
归档时间: |
|
查看次数: |
21540 次 |
最近记录: |