4

Possible Duplicate:
How to implement Unit of work in MVC: Responsibility

Hi. I am developing an ASP.NET MVC web application using the following architecture: UI -> Controller -> Service Layer -> Repository. The question here is where to expose the Unit Of Work pattern. For instance I have:

public class SomeController
{
    public ActionResult AnAction()
    {
        using(var unitOfWork = UnitOfWorkManager.Create())
        {
            try
            {
                this.ServiceA.Foo();
                this.ServiceB.Foo();

                unitOfWork.Commit();
            }
            catch(Exception ex)
            {
                unitOfWork.Rollback();
            }         
        }
    }
}

Is it ok for the controller to know about unit of work? What if we have several calls to different services but within the same action method and we need transactional behavior?

Community
  • 1
  • 1
Markus
  • 3,547
  • 10
  • 39
  • 55
  • 2
    Your question was also discussed in SO: http://stackoverflow.com/questions/2238428/how-to-implement-unit-of-work-in-mvc-responsibility – tshao Nov 09 '10 at 01:26

1 Answers1

4

We have built an application with the same architecture and our view was that the UOW class is used exclusively in the Services. Reasons:

  1. We think the actions should only have view logic so if possible should not know the business rules associated with using multiple repository calls
  2. Business logic rules should (As much as possible) be in a service. We have a our services use none or many repositories using the UOW class and a short lived context object.

The Action

public ActionResult List()
{
    var things = ThingService.GetAll();            
    return View(things);
}

The Service

public IEnumerable<Thing> GetAll()
{
    using (ObjectContext context = new Container(ConnectionString))
    {
        var work = new UnitOfWork(context);
        return work.Things.GetAll());
    }
}

Hope this helps

abarr
  • 1,140
  • 3
  • 13
  • 28
  • 2
    Thanks, but how did you handle the case when for instance one user action requires operations on several services, as in my case? According to your response, I assume that ServiceA object would contain a reference to ServiceB object and call method ServiceB.Foo() from ServiceA.Foo(). I think this complicates the architecture. – Markus Nov 09 '10 at 12:30
  • 3
    Markus in most cases our services are designed to encapsulate one transactions logic. So in this case if the Service handled all of the business logic and then needed to send an email (Another Service) it would know about that service (Injected using Dependency Injection). If it is something more complicated then the Command pattern over the Services lets you build up a transaction of services e.g. A flight booking is changed and that affects an associated car booking. But we did this so we could mix and match services, you might not need this flexibility ... – abarr Nov 09 '10 at 13:31
  • where do you call `Commit`? based on your example every service should call `Commit` by itself but in the case of multiple services interact with each other, you may end up with multiple trips to DB, right? – ebram khalil Jul 08 '14 at 12:00
  • @ebramtharwat I'm facing a similar problem right now when updating multiple items. Should I have a save method on my service that I call once everything is set? Should I have a instance of the UOW outside of my service to call Commit on. Should I have a save method that I pass a object in, method does nothing with the object, just call uow.commit(). – kheit May 15 '15 at 16:15
  • 1
    @kheit, there is no one valid solution for this problem. IMHO, you should call `uow.commit()` should be done from the layer that originally started the request which i believe that would be the presentation layer as it would be the most aware layer. the problem with that approach, is that in some cases you would need to save some data before entering another new data. Sorry for my late reply. – ebram khalil May 24 '15 at 15:13