A repository pattern is a pattern in which domain entities and data access logic are connected to each other using interfaces. In this patterns, the database logics are encapsulated using repositories that are independent of any ORMs like Entity Framework, Hibernate, etc. Repositories simply exposes methods that can be invoked from anywhere in the application. These methods encapsulated the database query logics behind the scenes. By implementing repository pattern, we are trying to minimize code duplication and create a loosely coupled systems. For example, if your project needs a query to show all the orders by a customer frequently, you can encapsulate that logic in a repository and expose the method that does the work behind the scene.
var orders=repository.getAllOrdersByCustomerId(int customerId);
Entity Framework provides similar implementation out of the box using dbsets. These dbsets represents database entities that are mapped to tables in the database. You can call methods like add, get, remove, find and so on using dbset type variable; however, this implementation doesn’t provide us the way to create scalable and loosely coupled systems. Later on if we decided to implement our database logics in a different way, we would have to change the entire implementation and the impact of these changes can very costly.
What is a uniofwork?
A unit of work is nothing but a completion of a unit or task. UnitofWork pattern are used to maintain, track, and save the states of objects that are affected by transactions. You might argue that dbcontext in Entity framework is like unitofwork; therefore, it is not necessary to have these in our project. Your argument is partially correct; however, the entity framework’s dbcontext is not sufficient enough to track changes in multiple domain objects repositories within the same transactions.
Create a context class
Create an interface that has common methods defined in them that will be implementated by all the repositories. For Example, methods such as Add, Get, and Find can be common across all the repositories.
Implement the above interface using a repository class
Create an interface for each type of repositories such as ICustomerRepository, IOrderRepository, INotificationRepository etc
Implement all of the interfaces from step 3
Create an interface IUnitOfWork that exposes all the repositories and add a method called Save()
Implement the interface from step above using a class called “UnitOfWork”
Write your client code like the following
Please find the following github link to look at a sample console application using Repository and UnitOfWork Pattern.