Reputation: 24150
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?
Upvotes: 2
Views: 941
Reputation: 6009
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.
Upvotes: 1