Unit of work sharing among many services in ASP.NET MVC 3

my controllers use 2 or more services. In turn, my services create and consume their own instance of the Unit of Work class (with access to the repositories).

I would like my services to share a single instance of an organizational unit instance and test it per unit. My questions:

  • Should I introduce a module of work and services to my controllers?
  • I will also need to attach a work unit to my services. where should i do this? Thank you very much.
+4
source share
3 answers

1) I do not think that the injection unit of work in the UI controller is a good idea, try to separate the logic and the transaction from the user interface.

2) Yes, you can use UoW in your service more preferably as a constructor introduced through the IoC container. some people design it as a static factory, but I prefer to use it as a parameter entered in the constructor

public class MyService : IMyService { IUnitOfWork _unitOfWork; public MyService(IUnitOfWork uow) { _unitOfWork = uow; } public void DoSomeOperation(SampleParam param) { _unitOfWork.BeginTrx(); // do some work _unitOfWork.Commit(); } } 

or using a static factory

 public class MyService : IMyService { public void DoSomeOperation(SampleParam param) { using(UnitOfWork.Start()) { // do some work } } } 
+5
source

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>(); //also make sure your IUnitOfWork is bound per request, obviously 

And finally, an example of Action

 [UnitOfWorkAction] public ActionResult SomeAction(int id) { //invoke your services here, and the uow will be automatically committed or rolled back when the action returns } 

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.

+7
source

I like the answer of Mohamed Abed, I have not received enough points to add a comment to his message, so I’ll just try to mention that in these cases you need to make sure that the Unit of Work is marked as a single unit or that it will not be shared between services.

+2
source

Source: https://habr.com/ru/post/899043/


All Articles