Skip to content

Repository and Unit of Work Pattern

The Repository pattern and Unit of Work pattern are used together most of the time. Therefore I will combine them in this post and show how to implement them both.

Definition Repository

The Repository mediates between the domain and data mapping layers, acting like an in-memory collection of domain objects. (“Patterns of Enterprise Application Architecture” by Martin Fowler)

Repository Pattern Goals

  • Decouple Business code from data Access. As a result, the persistence Framework can be changed without a great effort
  • Separation of Concerns
  • Minimize duplicate query logic
  • Testability

Introduction

The Repository pattern is often used when an application performs data access operations. These operations can be on a database, Web Service or file storage. The repository encapsulates These operations so that it doesn’t matter to the business logic where the operations are performed. For example, the business logic performs the method GetAllCustomers() and expects to get all available customers. The application doesn’t care whether they are loaded from a database or web service.

The repository should look like an in-memory collection and should have generic methods like Add, Remove or FindById. With such generic methods, the repository can be easily reused in different applications.

Additionally to the generic repository, one or more specific repositories, which inherit from the generic repository, are implemented. These specialized repositories have methods which are needed by the application. For example, if the application is working with customers the CustomerRepository might have a method GetCustomersWithHighestRevenue.

With the data access set up, I need a way to keep track of the changes. Therefore I use the Unit of Work pattern.

Definition Unit of Work

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes.  (“Patterns of Enterprise Application Architecture” by Martin Fowler)

Consequences of the Unit of Work Pattern

  • Increases the level of abstraction and keep business logic free of data access code
  • Increased maintainability, flexibility and testability
  • More classes and interfaces but less duplicated code
  • The business logic is further away from the data because the repository abstracts the infrastructure. This has the effect that it might be harder to optimize certain operations which are performed against the data source.

Does Entity Framework implement the Repository and Unit of Work Pattern?

Entity Framework has a DbSet class which has Add and Remove method and therefore looks like a repository.  the DbContext class has the method SaveChanges and so looks like the unit of work. Therefore I thought that it is possible to use entity framework and have all the Advantages of the Repository and Unit of Work pattern out of the box. After taking a deeper look, I realized that that’s not the case.

The problem with DbSet is that its Linq statements are often big queries which are repeated all over the code. This makes to code harder to read and harder to change. Therefore it does not replace a repository.

The problem when using DbContext is that the code is tightly coupled to entity framework and therefore is really hard, if not impossible to replace it if needed.

Repository Pattern and Unit of Work Pattern UML Diagram

Repository pattern UML diagram
Repository pattern UML diagram

The Repository pattern consists of one IRepository which contains all generic operations like Add or Remove. It is implemented by the Repository and by all IConcreteRepository interfaces. Every IConcreteRepository interface is implemented by one ConcreteRepository class which also derives from the Repository class. With this implementation, the ConcreteRepositoy has all generic methods and also the methods for the specific class. As an example: the CustomerRepository could implement a method which is called GetAllSeniorCustomers or GetBestCustomersByRevenue.

Unit of Work pattern UML diagram

The unit of work provides the ability to save the changes to the storage (whatever this storage is). The IUnitOfWork interface has a method for saving which is often called Complete and every concrete repository as property. For example, if I have the repository ICustomerRepository then the IUnitOfWork has an ICustomerRepositry property with a getter only. Additionally, IUnitOfWork inherits from IDisposable.

The UnitOfWork class implements the Complete method, in which the data get saved to the data storage. The advantage of this implementation is that wherever you want to save something you only have to call the Complete method from UnitOfWork and don’t care about where it gets saved.

Implementation of the Repository and Unit of Work Pattern

For this example, I created a console project (RepositoryAndUnitOfWork) and a class library (RepositoryAndUnitOfWork.DataAccess). In the class library, I generate a database with a customer table.

Next, I let Entity Framework generate the data model from the database. If you don’t know how to do that, check the documentation for a step by step walkthrough.

Implementing Repositories

After setting up the database, it’s time to implement the repository. To do that, I create a new folder, Repositories, in the class library project and add a new interface IRepositry. In this Interface, I add all generic methods I want to use later in my applications. These methods are, GetById, Add, AddRange, Remove or Find. To make the Interface usable for all classes I use the generic type parameter T, where T is a class.

IRepository

After the generic repository, I also implement a specific repository for the customer. The ICustomerRepository inherits from IRepository and only implements one method.

ICustomerRepository

After implementing all interfaces it’s time to implement concrete repository classes. First, I create a class Repository which inherits from IRepository. In this class, I implement all methods from the interface. Additionally to the methods, I have a constructor which takes a DbContext as Parameter. This DbContext instantiates a DbSet which will be used to get or add data.

Repository

The implementations of the methods are pretty straight Forward. The only interesting one might be the Find method which takes an expression as parameter. In the implementation, I use Where to find all entries which fit the Expression of the parameter.

Find method

The final step for the Repository pattern is to implement the CustomerReposiotry. This class derives from Repository and ICustomerRepository and implements the method from the interface. The constructor takes a CustomerDbEntities object as Parameter which is derived from DbContext and generated by Entity Framework.

CustomerRepository

Implementing Unit of Work

All repositories are created now, but I need a class which writes my data to the database, the unit of work. To implement this class, I first implement the IUnitOfWork interface in the repositories folder in the library project. This interface derives from IDisposable and has an ICustomerRepository property and the method Complete. This method is responsible for saving changes. The Name of the method could be Save, Finish or whatever you like best.

IUnitOfWork

Like before, I add the concrete implementation of IUnitOfWork to the repositories folder in the console application project. The constructor takes a CustomerDbEnties object as parameter and also initializes the ICustomerRepository. The Complete Method saves the context with SaveChanges and the Dispose method disposes changes.

UnitOfWork

Using the Repository and Unit of Work

The usage of the unit of work differs between a web application and a console application. In an MVC application, the unit of work gets injected into the constructor. In the console application, I have to use a using statement. I can use with unitOfWork.Customer.Method(), for example unitOfWork.GetBestCustomers(3). To save the changes use unitOfWork.Complete().

Using the unit of work

You can find the source code on GitHub. If you want to try out the example, you have to change to connection string in the App.config to the location of the database on your computer

Note: In this example, I always talked about writing and reading data from the database. The storage location could also be a web service or file drive. If you want to try my example, you have to change the connection string for the database in the App.config file to the Location of the database on your computer.

Conclusion

In this post, I showed how to implement the Repository and Unit of Work pattern. Implementing both patterns results in more classes but the advantages of abstraction increased testability and increased maintainability outweigh the disadvantages. I also talked about entity framework and that although it looks like an out of the box Repository and Unit of Work pattern, it comes at the cost of tight coupling to the framework and should not be used to replace the patterns.

Published inDesign Pattern

20 Comments

  1. Dominic Purnell Dominic Purnell

    this is really good. What is don’t understand if you are creating a repository of domain objects why do we use generics and assume the underlying db entity is one and the same class as the domain object?

    • The generic repository contains generic operations which all entities use. The methods are generic, so every entity can use it and I don’t have any problems in adding more entities later on. The repository of the domain object contains the generic methods like Save() and Delete() and also implement addition methods which only the used entity needs.
      For example the CustomerRepository implements general operations for the customer like Save(Customer) and also adds methods which are specific to the customer like GetAllCustomers().

      • Zephania Eliah Zephania Eliah

        Thanks for nice article but one of our concern have been performance as in UnitOfWork u have to instantiate all the repositories of the application when u have a project with two classes as in example is not that much complex issue but when the project grows things become cumbersome i think. We have one application that we implemented the unit of work and repository pattern as users grows the application becomes slow, we have to restart our server for sometimes to make things get back to normal.

          • Akhil Kumar Akhil Kumar

            Thanks a lot

  2. DS DS

    I have a question about this part:

    “The final step for the Repository pattern is to implement the CustomerReposiotry. This class derives from Repository and ICustomerRepository and implements the method from the interface. The constructor takes a CustomerDbEntities object as Parameter which is derived from DbContext and generated by Entity Framework.”

    I don’t quite understand where CustomerDbEntities comes from. Can you elaborate on how you arrived at this particular type?

    Many thanks.

  3. DS DS

    Never mind! On investigation of your source code, I see where this is.
    Thanks.

  4. Pedro Pedro

    Hi, excellent post!

    How do you handle the case of error with the UnitOfWork.Complete()? If you have to rollback the changes what will be your solution?

    Bye and thanks for your time!

  5. Hi Pedro,

    you could have a try catch in your Complete() method. If an exception occurs there, you for example log it and return 0, so the caller knows that something went wrong. Alternatively, your method which calls the Complete method could handle the exception. Though I think the first option is better.

  6. RepoUnit RepoUnit

    I really like your article. It’s shorter than most other articles about this topic.
    The section “Does Entity Framework implement the Repository and Unit of Work Pattern?” was really helpful for me because it confirmed my thoughts about this.
    In all other articles I saw that the UnitOfWork object is a property of the Repository object. So it’s exactly the other way around than is this article. I would also let the Repository object have a property storing the UnitOfWork object since the Repository pattern intends to provide a collection-like interface to the business layer. In your solution you can only access the Repositories via the UnitOfWork which is one additional redirection. If you don’t need a UnitOfWork accessing the collections should also work. What is the reason to do it like you did?
    In your solution you generate the DbContext object (maybe because UnitOfWork is the interface to the business layer) but the BusinessLayer should not know about implementation details (i.e. that Entity Framework is used).

    • Hi RepoUnit,
      The UnitOfWork object is not a property of the repository because I want to abstract the repositories behind it. This means that I can change all my repositories but don’t have to make a single change in all the other layers. (if I had used dependency injeciton)

      Yes you are right, the business layer shouldn’t know anything about the UnitOfWork. I wanted to keep this demo as simple as possible. Therefore everything is in the Main method and I also don’t use dependency injection.
      In a real world application, you would have your own business layer project and would inject the unit of work there.

  7. john john

    where is the Update method?

    • Hi John,

      this demo doesn’t have an Update method. You can add it in the IRepository and Repository classes.

      • john john

        Can I use the following for updates:

        DbSet DbSet = context.Set();
        var newEntity = DbSet.Add(entity);

        Thanks.

  8. Antonio Antonio

    Thanks for sharing your thoughts. I really appreciate your efforts and I am waiting for your next write ups thanks once again.|

  9. Launa Launa

    Very good post! We are linking to this particularly great post on our site. Keep up the good writing.|

  10. Rahul Rahul

    Hey, nice article only question is how you will implement an identity framework in this pattern I mean in which layer? I have read many articles in which the user manager and sign in manager are used within the controller itself which means giving the database calls from the controller. Any idea or article on this will help thanks.

    • Hi Rahul,

      In my eyes, a controller should never call the database directly. It should always be through the data layer. Depending on your solution structure but most solutions have an Api layer (controllers) a service layer and a data layer. The controller calls a service which calls a repository (in the data layer) to access the database.
      Using multiple projects also helps to abstract the database and you achieve Separation of Concerns. You can check my post about microservices to see the project structure I meant previously: https://www.programmingwithwolfgang.com/microservices-getting-started/

  11. Stremove Stremove

    The final part to look at is unit testing applications that use EF Core. One of the pluses of a repository pattern is you can replace it with a mock, when testing. So, using EF Core directly removed the option of mocking (technically you could mock EF Core, but it s very hard to do well).

    • Hi Stremove,

      yes you can easily mock repositories out of your services but you also have to test your repositories. To test repositories, I always use an in-memory database. Then you don’t have to mock anything and can use EF core functionality like Add or Update.

Leave a Reply

Your email address will not be published. Required fields are marked *

RSS
Follow by Email
LinkedIn
Share