The unit of work pattern within a asp.net mvc application
I have been looking at this excellant blog titled "NHibernate and the Unit of Work Pattern" and have a question regarding the best place to use UnitOfWork.Start in a asp.net mvc project.
My SLN is broken down into the following projects:-
MVC project
Repository
NHibernateUnitOfWork
I have an interface:-
public interface INameRepository
...
IList<Name> GetByOrigin(int OriginId)
...
I have a concrete implementation
public class NameRepository : INameRepository
...
public IList<Name> GetByOrigin(int OriginId) {
using (UnitOfWork.Start()) {
var query = session.Linq<...
return query;
}
}
...
My questio开发者_开发问答n is do I wrap all my methods inside all my repositories with using(UnitOfWork.Start()) or is there a better approach?
I am using nHibernate, asp.net mvc.
With the unit of work pattern, you don't put every dataaccess method in a separate unit of work. You use the unit of work around the whole work that needs to be done, which is in most cases in a web application a webrequest. The idea is that a request can fail, or succeed. When you add 2 items to the database during one request, the should be both added, or not. Not just one of them. In most cases, the easiest way to start a unit of work in a mvc (or other web) application is in the begin and end request methods of the global.asax
class Global
{
BeginRequest()
{
servicelocater.get<unitofwork>().start();
}
EndRequest()
{
var unit = servicelocater.Get<Unitofwork>();
try
{
unit.commit();
}
catch
{
unit.rollback();
throw;
}
}
}
class Repository<T>
{
public Repository(INHibernateUnitofwork unitofwork)
{
this.unitofwork = unitofwork;
}
public void Add(T entity)
{
unitofwork.session.save(entity);
}
}
I think Sharp Architecture solves this quite well. What they do is put the unit of work inside an ASP .Net MVC Action Filter. Basically you can define a transaction Action filter such as
public class TransactionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
UnitOfWork.Start();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
UnitOfWork.Stop();
}
}
and in your controller class put the Transaction attribute on your Action Result method
精彩评论