工作单元模式——在哪里使用?
我正在使用 ASP.NET MVC 3,并使用 NHibernate 和 Ninject 的存储库和工作单元模式。我看了几个例子(1,2) 来帮助实现 UoW,我只是不确定应该在哪里使用该工作单元。是否应该将其注入到我的控制器中,并在我的操作中手动调用提交和回滚?
以下是一些代码示例:
工作单元(接口扩展 IDisposable 并具有会话、提交和回滚)
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public ISession Session { get; private set; }
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
public void Dispose()
{
if (Session.IsOpen)
Session.Close();
}
}
我的 Ninject 模块的一部分:
Bind<IXXXRepository>().To<XXXRepository>().InRequestScope();
Bind<IYYYRepository>().To<YYYRepository>().InRequestScope();
...
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateConfiguration(Path.Combine(
HostingEnvironment.ApplicationPhysicalPath,
"bin",
"hibernate.cfg.xml")).BuildSessionFactory()).InSingletonScope();
Bind<ISession>().ToMethod(x => x.Kernel.Get<IUnitOfWork>().Session).InRequestScope();
我的所有存储库都继承自一个注入 ISession
的类,正如我所说在这篇文章的前面,我将 IUnitOfWork 注入到我的控制器中,并根据需要调用 Commit 和 Rollback。我这样做对吗?我是否应该只在进行更新或删除时调用 Commit,并且根本不用担心为选择调用它?这会在每个请求结束时留下一个挂起的事务吗?
I'm using ASP.NET MVC 3 and am using the repository and unit of work patterns with NHibernate and Ninject. I looked at a couple examples (1, 2) to help implement UoW, and I'm just not sure where I should be using the unit of work. Should it be injected within my controllers, and manually call Commit and Rollback in my actions?
Here's some code examples:
Unit of work (interface extends IDisposable and has Session, Commit and Rollback)
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public ISession Session { get; private set; }
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
public void Dispose()
{
if (Session.IsOpen)
Session.Close();
}
}
Part of my Ninject module:
Bind<IXXXRepository>().To<XXXRepository>().InRequestScope();
Bind<IYYYRepository>().To<YYYRepository>().InRequestScope();
...
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateConfiguration(Path.Combine(
HostingEnvironment.ApplicationPhysicalPath,
"bin",
"hibernate.cfg.xml")).BuildSessionFactory()).InSingletonScope();
Bind<ISession>().ToMethod(x => x.Kernel.Get<IUnitOfWork>().Session).InRequestScope();
All my repositories inherit from a class that gets an ISession
injected, and as I said earlier in the post I'm injecting the IUnitOfWork
into my controllers and calling Commit and Rollback as necessary. Am I doing this right? Should I only be calling Commit when I'm doing updates or deletes, and don't worry about calling it at all for selects? Will that leave a hanging transaction at the end of every request?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我喜欢使用 ActionFilter 围绕每个请求自动开始/提交工作单元。这对我 95% 的行为都很有效。对于一些更复杂的,我将注入 UoW 并从控制器或服务显式管理它。
我通常只是将 ISession 注入到 UnitOfWork 以及存储库中。存储库确实没有理由知道工作单元,它根本不应该接触事务。
I like to use an ActionFilter to automatically begin/commit the unit of work around every request. This works great for 95% of my actions. For the few more complex ones I'll inject the UoW and manage it explicitly from either the controller or the service.
I normally just inject the ISession to the UnitOfWork, as well as to the repositories. There's really no reason a repository should be aware of a unit of work, it shouldn't be touching the transaction at all.