4 Common Mistakes with the Repository Pattern

As part of my new ASP.NET Core course, I’ve been encouraging my students to post their code to GitHub. While reviewing various solutions, I’ve encountered a few common mistakes in the implementation of the repository pattern.

One repository per domain

You should think of a repository as a collection of domain objects in memory. If you’re building an application called Vega, you shouldn’t have a repository like the following:

public class VegaRepository 

Instead, you should have a separate repository per domain class, like OrderRepository, ShippingRepository and ProductRepository.

Repositories that return view models/DTOs

Once again, a repository is like a collection of domain objects. So it should not return view models/DTOs or anything that is not a domain object. I’ve seen many students using AutoMapper inside their repository methods:

public IEnumerable<OrderViewModel> GetOrders() 
     var orders = context.Orders.ToList();

     return mapper.Map<List<Order>, List<OrderViewModel>(orders);

Mapping is not the responsibility of the repository. It’s the responsibility of your controllers. Your repositories should return domain objects and the client of the repository can decide if it needs to do the mapping. By mapping the domain objects to view models (or something else) inside a repository, you prevent the client of your repositories from getting access to the underlying domain object. What if you return OrderViewModel but somewhere else you need OrderDetailsViewModel or OrderSnapshotViewModel? So, the client of the repository should decide what it wants to map the Order object to.

Save/Update method in repositories

Yet another very common mistake! As I’ve explained in my YouTube video before, your repositories should not have a Save() or Update() method. I repeat: think of a repository as a collection of domain objects in memory. Do collections have a Save() or Update() method? No! Here’s an example:

var list = new List<int>();

list.Save();    // doesn't exist!
list.Update();  // doesn't exist!

Another reason your repositories should not have a Save() method is because sometimes as part of a transaction you may work with multiple repositories. And then you want to persist the changes across multiple repositories in one transaction. Here’s an example:



Can you see the problem in this code? For each change, we need a separate call to the Save() method on the corresponding repository. What if one of these calls to the Save() method fails? You’ll end up with a database in an inconsistent state. Yes, we can wrap that whole thing inside a transaction to make it even more ugly!

A pattern that goes hand in hand with the repository pattern is the unit of work. With the unit of work, we can re-write that ugly code like this:


Now, either both objects are saved together or none are saved. The database will always be in a consistent state. No need to wrap this block inside a transaction. No need for two separate calls to the Save() method!

If you want to learn how to implement the repository and unit of work pattern together, watch my YouTube video here.

Repositories that return IQueryable

One of the reasons we use the repository pattern is to encapsulate fat queries. These queries make it hard to read, understand and test actions in ASP.NET MVC controllers. Also, as your application grows, the chances of you repeating a fat query in multiple places increases. With the repository pattern, we encapsulate these queries inside repository classes. The result is slimmer, cleaner, more maintainable and easier-to-test actions. Consider this example:

var orders = context.Orders
    .Include(o => o.Details)
        .ThenInclude(d => d.Product)
    .Where(o => o.CustomerId == 1234);

Here we are directly using a DbContext without the repository pattern. When your repository methods return IQueryable, someone else is going to get that IQueryable and compose a query on top of it. Here’s the result:

var orders = repository.GetOrders()
    .Include(o => o.Details)
        .ThenInclude(d => d.Product)
    .Where(o => o.CustomerId == 1234);

Can you see the difference between these two code snippets? The only difference is in the first line. In the first example, we use context.Orders, in the second we use repository.GetOrders(). So, what problem is this repository solving? Nothing!

Your repositories should return domain objects. So, the GetOrders() method should return an IEnumerable. With this, the second example can be re-written as:

var orders = repository.GetOrders(1234);

See the difference?

What are the other issues you’ve seen in the implementation of the repository pattern? Share your thoughts!

If you enjoyed this article, please share it.

Hi! I’m Mosh Hamedani and I help ambitious developers take their coding skills to the next level. Over the last 3 years, I’ve taught over 200,000 students through my online courses and my YouTube channel has been watched over 5.7 million times! It’s my mission to make coding and software engineering accessible to everyone.

Related Posts

Tags: ,

32 responses to “4 Common Mistakes with the Repository Pattern”

  1. Dayshine says:

    “Mapping is not the responsibility of the repository. It’s the responsibility of your controllers”

    What about mapping from your repository object to your domain object?

    This is all good advice for the interface. But aren’t you glossing over the implementation part of your repository pattern? None of this is actual *implementation*.

  2. Saeid says:

    About “Repositories that return view models/DTOs”
    Suppose your domain model has 20 fields with large amount of data and you want to use only 3 fields here, you have to fetch the whole row first and then map it, which is very inefficient.

    • admin says:

      Very good point!

      What you’re referring to here is a simple data structure and not a domain object. You want this structure with 3 properties only for a specific view (or multiple views) in the application. This data structure is nothing but a data container. It’s not a domain object. It doesn’t have any methods, neither does it encapsulate any business rules.

      To expand more on your example, those 3 properties may be mapped to a subset of columns in 1 table, or they can be the result of joining N tables and picking 3 columns. In either case, it is not a domain object, and by definition, it doesn’t fit the definition of the repository pattern.

      These objects are only used for the read operations and for these I use a separate group of classes, which I call providers (eg CustomerProvider). It has a bunch of methods for querying customer data mainly for reporting. In the implementation of this provider, you can also use AsNoTracking() to improve the performance. You wouldn’t do that in your repository implementations because you need to keep track of changes to your domain objects and persist them in the database. You may even use a stored procedure for performance optimization.

      The more complex your application gets, the more you may want to consider separating the read and write models. And then eventually you’ll find in the CQRS realm.

      • Leon says:

        Would you care to elaborate on what you call Providers? I’m really curious because I often find myself using AsNoTracking() and really large “reporting” or “stats” queries joining multiple tables and I don’t know where to put them.

        Also unsure if it is okay in this pattern to return a custom class of combined domain entities that is not a ViewModel but just a data structure which then can be mapped to a ViewModel.

        Thanks a lot for your courses. Landed my first software dev job much because of you.

        • Mosh says:

          The scenario you’re talking about is for reporting. In these situations, you’re not working with your domain objects. As you said, you may join multiple tables or select a subset of their columns and return the data in a structure that fits your reports. So, you wouldn’t be using a repository in this class. You could have a provider class that is purely used for returning read-only data with AsNoTracking. You may have several reports around employees. You can have EmployeeProvider with methods such as GetEmployeesReturningNextYear(), GetEmployeesEligibleForIncentives(), etc.

          • Leon says:

            Alright. What are the objects being returned then? Viewmodels? Just projected domain objects which later can be mapped to viewmodels?

            I assume these Provider classes fit into Persistance layer and not core? Should I then do like repositories put interfaces in Core? Then use DI with the interface? Do providers have access tp Context? Because like Saeid said with these large reporting queries you would want to optimize Sql generation which i guess is easier with Context.

            Thank you so much for your time and effort.

          • Leon says:

            In your ASP.NET Core Udemy tutorial you had a VehicleRepository.cs return a QueryResult – which is not an entity? Would that method fit more into a Provider class?

          • Leon says:

            I hope you get a chance to answer my latest questions here.. Perhaps even write a blog post or make a video? I just got really confused and I think this is largely misunderstood by many others!

          • Leon says:

            Continued experimenting with this. Another question came up. I guess automapper will be heavily used in provider classes if they return viewmodels/resources. Utilizing IQueryable extension ProjectTo().

            Now how do I unit test provider methods if they are dependent on automapper?

          • Leon says:

            You commented somewhere else that repository is for getting data and mapping is the responsibility of controller but now I’m thinking EVERY Get request should just go through a “Provider” returning ViewModels for better generated SQL and performance..?

            Sorry if I’m asking too much.

      • Leon says:

        Also just in general when returning objects from repository that will be used for readonly situations such as details pages. Got confused when you said AsNoTracking() doesn’t fit in here.

  3. Rahul says:

    Hi Mosh,

    @’Save/Update method in repositories’

    Lets assume that we need convert existing application to its latest tech with pattern, where the request or update are done with existing SQL or Stored procedures.

    Please let us know how do i implement the Unit of work complete method (needs to be utilized existing stored procedures for update function) and if not please prove as stated ‘Repositories should not have a Save() or Update() method’

    • admin says:

      Hi Rahul,

      I recommend you to watch my YouTube video first and then read my comment below:

      Regarding your question about implementing the unit of work for an application with existing stored procedures: you don’t really need to implement a unit of work from scratch. One complex part of this implementation is about keeping track of object changes in memory. DbContext already does that for you and you don’t need to re-implement it. You can map the CRUD operations to stored procedures in the database:

      When EF tries to generate queries for inserting, updating, deleting and getting data, it’ll call your stored procedures.

      Finally, you wrap your DbContext with an IUnitOfWork interface do decouple it from your application and simplify testing. Again, I’ve explained that in my YouTube video.

  4. Clayton says:

    Hi Mosh,

    I agree with you that the repository must return only domain entities. If you want to return ViewModel objects, it’s possible to create a Service layer that would be responsible for get domain entities using a repository and convert to ViewModels. Finally, the controller(mvc or webApi) could use these services and know nothing about the entities.

    Leave your comments.

    Have a nice day!

    • admin says:

      Hi Clayton,

      Services should not return ViewModels either! A ViewModel is part of the presentation layer which sits above the service layer. Mapping of domain objects to ViewModels is the responsibility of whoever wants to display those objects. In an ASP.NET MVC application, it’s the controller, in a WPF application it’s the Form (or Window).

      Services are often misunderstood. Technically, your services should be used only for the write operations and not for reading data. It took me a little while to really grasp this. The reason is that if a controller needs some data from the database, it can simply use the repository interfaces to get the data. There is no need to go through a service layer for getting data. With this implementation, you’ll end up with services methods that have 1 line of code, which is simply delegating to the repository. What’s the point of these methods? Nothing but increasing the development and maintenance cost. I had a lot of services like these several years ago but eventually, I came to this realization that these methods are redundant and add absolutely no value.

      Just to clarify, controller uses the repository interface (not the implementation). So it doesn’t go straight to the data access layer. Repository interfaces are part of the business layer or the core domain.

      Hope that helps!

  5. Shehab says:


    If we return IEnumerable from the repository and the entity has a large dataset, would that be slower than returning IQueryable with a ‘fatter’ query inside the repository?
    I think not because the service call to the repository is filtering the records before it get called but I wanted to see what you think.

    Thanks in advance.

    • admin says:

      I’m not quite sure what you mean. A fat query can get slow when dealing with large datasets. Whether you return IQueryable from your repositories (which you shouldn’t) and then do a ToList() somewhere else, or do the ToList() inside the repository (which you should), the performance is the same.

      • Ali Dehqan says:

        Hey mosh,
        There are many questions about implementing repository pattern.
        Assume a table with large data and many columns with nvarcharmax columns:

        1- As you said in your videos and this post:

        Repository Layer : GetUsersByFilter() -> returns IEnumerable

        Because we are fetching all of the columns it doesn’t seem to be efficient.
        We are returning domain IEnumerable with all of the fields and constraints implemented on domain object and its fields.

        2- Another way

        Repository Layer : GetUsersByFilter1() -> returns IEnumerable
        Repository Layer : GetUsersByFilter2() -> returns IEnumerable
        Repository Layer : GetUsersByFilter3() -> returns IEnumerable
        Repository Layer : GetUsersByFilter4() -> returns IEnumerable

        Which doesn’t return all of the UserDomain columns in each method. We can select fields which we need in select query

        GetUsersByFilter1(FilterModel filterModel){

        return _context.Users
        .Where( //filter goes here )
        .Select(x => new UserDomain{
        //just set 4 of 20 columns

        3- Another another way

        Repository Layer : GetUsersByFilter() -> returns IQueryable

        Service Layer: Implement multiple methods according presentation layer needs with different select queries and filters.


        I think the first way is not efficient in large databases.

  6. chong says:

    “Instead, you should have a separate repository per domain class, like OrderRepository, ShippingRepository and ProductRepository.”

    Hi Mosh,
    Do you mind to share your thought about Generic Repository pattern? What do you think about it?

    • admin says:

      Generic repository is good as long as your methods don’t method IQueryable. Otherwise, it’s like you’re wrapping DbSet with another class with the same interface. No point in doing that!

      It’s useful when you wanna get simple objects (like reference data) without having to create a separate repository for each entity.

  7. Jarbas Carvalho says:

    Hi Mosh,

    What about OData integration that needs IQueryable?

  8. Neo says:

    Great article. From the last section, I formulated the following coding convention for my team which I think is highly useful:

    “For repository class methods, never return a IQueryable object. Always enumerate or convert it first (e.g., ToArray, ToList, AsEnumerable).”

    The reasoning being that IQueryable would allow the caller to build on this and ultimately modify the SQL query that is executed on the database. This can potentially be dangerous in terms of DB performance, but it is more about SoC. The caller doesn’t care about the data source; it just wants the data.

  9. Alex says:

    How would you return an entity with only specific columns (e.g. having the SQL built only query what you need) if neither the repository nor the service are ‘allowed’ to return IQueryable or DbSet ?

  10. Rafael says:

    Hi, Mosh

    ” a repository is like a collection of domain objects. ”

    yeah thats right and it should only return domain objects.I agree with that but I have a question

    “Mapping is not the responsibility of the repository.”

    but what if my domain entity is different that my data model entity?? who and where I have to make the mapping to persist the data.


  11. So you say not to save/update in repositories. That sounds good, but could you answer me this:

    Where should I call .SaveChanges on a DbContext when using an IoC-container?
    If I do manual injection I can easily use the DbContext as a unit of work.
    But I fail to see how to solve this when using something like Unity or an DI-container.
    I’m also using services which have the repositories injected.

    Thanks for your time!

  12. Georgi Karavasilev says:

    Hello Mosh!

    What about mapping in repositories when we have domain model and persistent model? Where we should do the transformation between the different type of objects? I usually have a separate folder with static classes and call it in the repository before the write methods and after the read ones.

    Will be glad to hear your opinion! Greets!

  13. Masoud Shabanloo says:

    Hi mosh

    I watched your Repository video and read this blog post, both more than 3 times. It’s really good explained and I should say you are one of my favorite bloggers. There is something in this post made me confused; The last part of the post. You emphasized, Repository should never return IQueryable, because it results in performance issue. But I read something that sounds contradictory.
    This is the confusing part:

    IEnumerable: While querying data from database, IEnumerable executes select query on server side, load data in-memory on client side and then filter data. Hence does more work and becomes slow.

    IQueryable: While querying data from database, IQueryable executes select query on server side with all filters. Hence does less work and becomes fast.

    It’s opposite of your advice. If it’s true, why we should not use IQueryable instead of IEnumerable.

    And something else, What about situations that we want to use OData; As you know it’s better to use IQueryable instead of IEnumerable in OData queries.

    please let me know your opinion.

    Thank you

  14. Hello Mosh!

    What about the navigation properties that comes with an order when I execute the following query and is there any need of Include?

    public Order GetOrder(Expression<Func> whereExp)
    return _OrderRepositories.Get(whereExp);//It will get its related record as well

Leave a Reply