0

This is a beginner question for Unity so forgive me.

In my Unity Config I have the following that creates my database context (Entity Framework), Unit of Work, and a Repository pattern object (from reverse pocos and generic repo/uow):

container
.RegisterType<IDataContextAsync, myDbContext>(
    new PerRequestLifetimeManager(),
    new InjectionConstructor(new object[] { connString }))
.RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager())
.RegisterType<IRepositoryAsync<Contact>, Repository<Contact>>()

In Microsoft MVC, my controllers are injected with services:

public myController(IContactService contactService) {
    _contactService = contactService;
}

My services are injected with repositories:

public class ContactService : Service<Contact>, IContactService 
{
    public ContactService( IRepositoryAsync<Contact> repository) {...}
}

Everything works well but I'm not sure how to access the Unity created Unit of Work object in the Controller to save changes: UnitOfWork.SaveChangesAsync()

Without DI, here's how to create the objects:

IRepositoryProvider repoProvider = new RepositoryProvider( new RepositoryFactories());
IDataContextAsync context = new MyDbContext();
IUnitOfWorkAsync uow = new UnitOfWork(context, repoProvider);
IRepositoryAsync contactRepo = new Repository<Contact>(context, uow);

...  // database changes

uow.SaveChangesAsync(); // In the Controller

The obvious thing to do is reference a UOW in the Controller constructor function, but how would Unity use that same object for the Service, and how would the Service use it for the Repositories?

Zachary Scott
  • 20,968
  • 35
  • 123
  • 205
  • 1
    I think it is best to keep the controllers oblivious to the fact that there is a unit of work. This makes the controllers simpler and prevents bugs because someone forgot to save the unit of work. So its better to move this responsibility to the used service, or perhaps even better, wrap services with decorators that will commit the uow automatically. And example of this can be seen [here](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91). – Steven May 27 '15 at 14:58
  • Related: https://stackoverflow.com/questions/10585478/one-dbcontext-per-web-request-why – Steven May 27 '15 at 14:59
  • @Steven So given we have the Service handle saving changes, how does the Service get a link to the same UOW object referenced by the repositories while not creating these objects itself? – Zachary Scott May 27 '15 at 16:50
  • I think the q/a I linked to gives answers to this question and more. – Steven May 27 '15 at 17:02
  • @Steven First of all good articles. After printing, reading, and highlighting both articles, I can see you could decorate the UnitOfWork with a .Handle() method, but I still fail to understand where you'd get a reference to the object holding .Handle() so you could call it inside the Service? – Zachary Scott May 27 '15 at 19:27
  • What I typically do is have a command handler decorator that calls Commit. This way both the Controller and Command Handler are oblivious to committing. – Steven May 27 '15 at 19:40
  • @Steven I was missing the obvious Singleton pattern on the UnitOfWork and dbContext in Unity's registration, so simply referencing the unit of work and repository objects in the constructor parameters gives you the object to .SaveChanges(). Based on your writing though, I do wonder how one would group certain repositories together in separate UnitsOfWork, like for Product and Customer. – Zachary Scott May 28 '15 at 15:36

1 Answers1

1

You have already solved your own problem...

Your UnitOfWork class is registered with the PerRequestLifetimeManager. This lifetime will ensure that anytime a UOW is resolved within the same MVC request you will receive the same instance. So you will automatically get the same instance of your UOW passed to your controller constructor as you will get passed to your repository constructor.

TylerOhlsen
  • 5,485
  • 1
  • 24
  • 39
  • Interesting! So you are saying that if I have constructor function parameters of the unit of work and a repository in my Service that Unity will create the Unit Of Work object and use that object to create the repository too? So all I need to do is put the IUnitOfWorkAsync reference in the constructor function of any Service then call the .SaveChangesAsync() and the repository changes will persist to the database? – Zachary Scott May 28 '15 at 15:24
  • That's correct. Take a look at other lifetime managers as well so you understand the scope of your objects. This is important for threading issues (which are intermittent and nasty to troubleshoot). – TylerOhlsen May 29 '15 at 01:58