Overview
The Repository and Unit of Work (UoW) pattern are very useful patterns to create an abstraction level over the DbContext that is provided by Entity Framework. A much heard excuse not to use repositories is that EF itself already works with repositories (the DbContext) and a UoW (in the SaveChanges method). Below are a few examples why it is a good thing to create repositories:
- Abstract away some of the more complex features of Entity Framework that the end-developer should not be bothered with
- Hide the actual DbContext (make it internal) to prevent misuse
- Keep security checks and saving and rollback in a single location
- Force the use of the Specification pattern on queries
A Unit of Work (UoW) is a a combination of several actions that will be grouped into a transaction. This means that either all actions inside a UoW are committed or rolled back. The advantage of using a UoW is that multiple save actions to multiple repositories can be grouped as a unit.
A repository is a class or service responsible for providing objects and allowing end-developers to query data. Instead of querying the DbContext directly, the DbContext can be abstracted away to provide default queries and force required functionality to all end-developers of the DbContext.
A Unit of Work (UoW) is a a combination of several actions that will be grouped into a transaction. This means that either all actions inside a UoW are committed or rolled back. The advantage of using a UoW is that multiple save actions to multiple repositories can be grouped as a unit.
A repository is a class or service responsible for providing objects and allowing end-developers to query data. Instead of querying the DbContext directly, the DbContext can be abstracted away to provide default queries and force required functionality to all end-developers of the DbContext.
Creating a Unit of Work
A UoW can be created by simply instantiating it. The end-developer has the option to either inject the DbContext or let the DbContextManager take care of it automatically.
1: using (var uow = new UnitOfWork<MyDbContext>())
2: {3: // get repositories and query away
4: }
Creating a repository
A repository can be created very easily by deriving from the EntityRepositoryBase class. Below is an example of a customer repository:
1: public class CustomerRepository : EntityRepositoryBase<Customer, int>, ICustomerRepository
2: {3: public CustomerRepository(DbContext dbContext)
4: : base(dbContext)
5: {6: }
7: }
8:
9: public interface ICustomerRepository : IEntityRepository<Customer, int>
10: {11: }
Retrieving repositories from a Unit of Work
Once a UoW is created, it can be used to resolve repositories. To retrieve a repository from the UoW, the following conditions must be met:
- The container must be registered in the ServiceLocator as Transient type. If the repository is declared as non-transient, it will be instantiated as new instance anyway.
- The repository must have a constructor accepting a DbContext instance
To retrieve a new repository from the UoW, use the following code:
1: using (var uow = new UnitOfWork<MyDbContext>())
2: {
3: var customerRepository = uow.GetRepository<ICustomerRepository>();
4:
5: // all interaction with the customer repository is applied to the unit of work
6: }
Saving a Unit of Work
It is very important to save a Unit of Work. Once the Unit of Work gets out of scope (outside the using), all changes will be discarded if not explicitly saved.
1: using (var uow = new UnitOfWork<MyDbContext>())
2: {
3: var customerRepository = uow.GetRepository<ICustomerRepository>();
4:
5: // all interaction with the customer repository is applied to the unit of work
6:
7: uow.SaveChanges();
8: }
References
http://blog.catenalogic.com/post/2013/02/27/Entity-Framework-Unit-of-Work-and-repositories.aspx
Summary
The repository and unit of work patterns are both very powerful if implemented correctly. They provide a lot of flexibility, extensibility and lower the development and testing friction.
No comments:
Post a Comment