When to use Unit of Work Pattern in application?
A software design pattern is a general reusable solution to a common occurring problem within a context in software design. In this post, I’ll tell you when to use Unit of Work (UoW) pattern in application. With correct understanding of the concepts, this knowledge can also be applied to a ASP.NET MVC or Web API application. I’ll use ASP.NET MVC web application to explain examples in this post.
I’ve covered when to use Repository pattern in application previously and it will be good to go through that post if you are new to these two design patterns as these two patterns are often used together in a web application.
Unite of Work (UoW) pattern
Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
– P of EAA – Martin Fowler
This pattern basically allows us to efficiently track the data that is pulled in and out of a database. There can be cases where the data is not written back into the database while new objects are created or removed when objects are removed. Also, if you are changing the database with each change to your object model, this can lead to lots of very small database calls, which ends up being very slow. For more details, please refer to the link quoted above.
Many developers use Repository pattern to save or update entities in the database which is not correct. A repository of an entity should only be used as a collection in memory and actions like add, update or delete should be applied only to the collection. And that collection should then be used to access domain objects. A repository should not save the changes as you may used more than one repository, make changes to those objects due to some business transaction and if save is available publicly in all these repositories then this can be a problem. Which save method will you use in this case?
Ideally to completely decouple the business logic layer from persistence layer, unit of work pattern can be used as it can easily coordinate the writing out of changes made to objects using repository pattern. So, saving changes is the responsibility of unit of work. No matter how many repositories are used to change the objects, we can then ask a unit of work to complete the changes from one central place. This will take care of the writing out of all the changes to those objects.
Let’s rework on the example from my previous post below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
public class EventsController : Controller { private readonly ApplicationDbContext _context; private readonly UnitOfWork _unitOfWork; public EventsController() { _context = new ApplicationDbContext(); _unitOfWork = new UnitOfWork(_context); } public ActionResult Details(int id) { var event = _unitOfWork.Events.GetEvent(id); if (event == null) return HttpNotFound(); var viewModel = new EventDetailsViewModel { Event = event }; return View("Details", viewModel); } [Authorize] public ActionResult MyEvents() { var userId = User.Identity.GetUserId(); var events = _unitOfWork.Events.GetUpcomingEventsByArtist(userId); return View(events); } [Authorize] [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(EventFormViewModel viewModel) { if (!ModelState.IsValid) { viewModel.Genres = _unitOfWork.Genres.GetGenres(); return View("EventForm", viewModel); } var event = new Event { ArtistId = User.Identity.GetUserId(), DateTime = viewModel.GetDateTime(), GenreId = viewModel.Genre, Venue = viewModel.Venue }; _unitOfWork.Events.Add(event); _unitOfWork.Complete(); return RedirectToAction("MyEvents", "Events"); } } |
As you can see the highlighted statements in the code above, controller consumes an object of type UnitOfWork
class to access events, genres repositories and also calls Complete
method to complete a unit of business work or transaction after changing objects using different repositories.
This way, a controller doesn’t need to use any repositories directly and it can just rely on object of type UnitOfWork
. Let’s see its definition:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class UnitOfWork { private readonly ApplicationDbContext _context; public EventRepository Events { get; private set; } public GenreRepository Genres { get; private set; } public UnitOfWork(ApplicationDbContext context) { _context = context; Events = new EventRepository(context); Genres = new GenreRepository(context); } public void Complete() { _context.SaveChanges(); } } |
In the code above, the repositories are used as a collection and only the constructor initialises these repositories with a DbContext
. This class only has one method named Complete
that internally calls save changes on the context which saves all the changes in the database. The code for repository is still similar that you can see in my previous post.
This sums up my post that explains when to use unit of work pattern in application. In the current version of examples shown here, controller directly relies on DbContext
and UnitOfWork
concrete classes. If you would like to learn how to decouple these dependencies then please subscribe to my blog as I’ll be writing a post regarding this soon.