I like combining DI with an action filter, this way the container can control the scope of the unit, but begin / commit / rollback gets called automatically for you, and you donβt have to fuss about it on every action.
This is a bit complicated because, as a rule, actionfilters are NOT re-created for each request, so when you have a dependency that you want to receive for the request (work unit), you need to work a little.
Here's how I do it using Ninject, and Ninject.Web.Mvc
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class UnitOfWorkAction : Attribute { } public class UnitOfWorkActionFilter : IActionFilter { private IUnitOfWork _unitOfWork; public UnitOfWorkActionFilter(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public void OnActionExecuting(ActionExecutingContext filterContext) { _unitOfWork.Begin(); } public void OnActionExecuted(ActionExecutedContext filterContext) { if (filterContext.Exception == null) { try { _unitOfWork.Commit(); } catch { _unitOfWork.Rollback(); throw; } } else { _unitOfWork.Rollback(); } } }
Then I set up the use of the attribute in App_Start / NinjectMVC3.cs
kernel.BindFilter<UnitOfWorkActionFilter>(FilterScope.Action, 0) .WhenActionMethodHas<UnitOfWorkAction>();
And finally, an example of Action
[UnitOfWorkAction] public ActionResult SomeAction(int id) {
It is also worth noting that this approach allows you to perform dependency injection with your action filter, rather than just embedding properties, which I really prefer.
source share