There are many blog posts and misconceptions about Repository Pattern, especially since the introduction of the OR/M libraries, like Entity Framework. In this article, we will investigate why this pattern is still useful, what are the benefits of using it and how we can use it in combination with Entity Framework. Even though Microsoft defines its DbContext and DbSet classes as a replacement for this pattern, we will see how this pattern still can help us make our code cleaner.
Let’s start with the definition of Repository Pattern. One of the best definitions of this pattern could be found in Martin Flower’s book Patterns of Enterprise Architecture:
A Repository mediates between the domain and data mapping layers, acting
like an in-memory domain object collection.
Why is this definition so cool, one might ask. Well, I personally like it because of the way it emphasizes two very important attributes of Repository pattern. The first attribute is that this pattern is an abstraction that aims to reduce complexity. The second important attribute is that this pattern is, in fact, an in-memory collection that mirrors database tables.
Repository Pattern Benefits and Misconceptions
Even if we use Entity Framework, we might end up with a lot of duplicate query code. For example, if we are implementing blog application and we want to get the most viewed articles in a few places, we might end up with repeated query logic which would look something like this:
We could end up with even more complicated queries, that potentially could be repeated through the code. Changing and maintaining this kind of code is not something that could be done in an easy manner. So, we still call our Repository to help us with this. We can encapsulate that behavior inside Repository and just call it like this:
It is much cleaner this way, isn’t it? Plus, if we want to change something in this logic, we will do it only in one place, which is a huge benefit. There you go, the first benefit of using Repository Pattern – no duplicate query logic.
The second obvious benefit is that it separates application code from persistence framework, and with that from the database that we are using. Basically, we could use different OR/M in our repository, or use completely different technology, like MongoDB or PostgreSQL, for example. Looking at the changes in the database trends in the last decade it is quite obvious why we would like to have flexibility like this.
The last, but probably one of the main benefits of using this pattern is that it eases unit testing. However, people often have the misconception that this pattern enables you to test data access layer in an easier manner. That is not true, but it is becoming a great asset in testing business logic. It is easy to mock repository implementation in the business logic.
Repository Pattern Overview
As we already mentioned, Repository is an in-memory collection of objects and that collection needs to have an interface using which we can access elements from that collection. That is why Repository should expose classical CRUD operations. Some people choose to skip Update operation because updating an object from the in-memory collection is essentially getting it and changing its value. I am one of those people 🙂 Of course, if you like it you can implement this function as well.
To sum it up, this is how repository interface and implementation looks like:
- Add – Method that will add an object of defined type T into our repository
- Remove – Method that will remove the object of defined type T from our repository
- Get – Method that will get an object of defined type T from our repository
- GetAll – Method that will get all objects from our repository
- Find – Method that will find and retrieve objects that match certain criteria from our repository
Entity Framework Brief Overview
At this moment we know that we will use Entity Framework and if you are not familiar with it you can check MSDN articles about it. In essence, Entity Framework is an object-relational mapper (O/RM) that enables .NET developers to work with a database using .NET objects. It eliminates the need for most of the data-access code that developers usually need to write. In a nutshell, it maps code objects to database tables and vice versa.
There are two approaches when it comes to using EntityFramework. The first one is called database-first approach. In this approach, we create a database and that use Entity Framework to create domain objects and to build code on top of that. The second one is called code-first approach. This is the approach that we will for building our Repository.
There are two important classes that we need to know – DbContext and DbSet. DbContex
Tests, Mocking and Implementation
Cool, now that we know how our Repository should look, we can start writing our tests for Repository class. One small note before we continue, in this example, I am using xUnit unit test framework and Moq mocking framework. Also, in the spirit of TDD, we will write our tests first and implementation afterwards. Apart from that testing type that will be used in this example is simple TestClass, and here is how it looks:
Very simple, right? It just has one property – Id. Let’s define how the interface of our Repository should look so we can understand our implementation better later:
Ok, let’s now see what the test for Add method looks like.
There are quite a few things that require explanation here. Firstly, the assumption is that Repository pattern will rely on DbContext class and that it will receive it through the constructor. That is why in the Arrange section of the test we mocked this class. We created a mock object of the DbSet class, as well. Then we set it up in a way that Add method of the DbSet returns testObject,
This is done like this so we can later test these methods being called, which is something you can see in the Assert part of the test. To sum it up, we mock the DbContext and DbSet, then we call the Add method of the repository and finally, we finally verify those methods from mock objects that have been called.
Implementation of this method is very straight-forward. Here it is:
Now you can see why we needed to mock Set method of the DbContext. This method returns a non-generic DbSet instance, using which we can access to entities of the given type in the context. Then we use that instance in the method to add another object.
Implementation of this method is similar to the implementation of the Add method. Let’s see what the test looks like:
Almost the same as for the Add method, we just need to setup Remove method of the DbSet. Here is how the implementation of the Repository class looks once we add Remove method:
Now, since during the implementation of the Add method we properly initialized DbContext and DbSe
During the implementation of the Get method, we are following the same principles. Test for this method looks like this:
Repository class after the addition of the Get method looks like this:
For the GetAll method, we need to shake things up a little bit. This method needs to return the list of objects. This means that we need to create a list of TestClass objects and return it trough DbSet. Effectively this means that we need to mock part of the DbSet that implements the IQueryableinterface in tests. Here is how it is done:
We needed to mock Provider, Expression, ElementType and GetEnumerator(
After learning how to mock IQueryable in the previous example, writing tests for Find method is much easier. We follow the same principle we used for the GetAllmethod. The test looks like this:
And finally, complete implementation of the Repository class looks like this:
A lot of people argue that if we are going to use DbContext and DbSet we don’t need to implement Repository Pattern and Unit of Work. If you ask me if this is the case, I would say to you that it depends on the type of problem. In this article, you had the chance to see how to build and test generic Repository using Entity Framework. If you choose to use DbContext and DbSet, there are still some useful tips that you could use from this article, like how to mock these classes. Either way, if you want to learn more about good practices that would make your code better, check out my video course – Introduction to TDD in C#.
Thanks for reading!
Read more posts from the author at Rubik’s Code.