Software design patterns are designed to solve specific problems with the right context, and if used inappropriately, they'll lead to extra unnecessary complexity without providing any values.
So, what are the problems that the repository pattern aims to solve?
1- Minimizing duplicate query logic: in large applications, you may find many complex LINQ queries duplicated in a few places. If that's the case, you can use the repository pattern to encapsulate these queries and minimise duplication.
2- Better separation of concerns: Imagine a complex query to get the top selling courses in a given category that involves eager loading, joining, grouping, filtering, etc.
When you implement such large complex queries in your services/controllers, you'll end up with fat services/controllers. These classes become hard to unit test as they'll require a lot of noisy stubbing. Your unit tests become long, fat, and unmaintainable.
If you're facing this problem, perhaps you might consider using the repository pattern. In this example, we can encapsulate the complex query to get top selling courses in a repository:
courseRepository.GetTopSellingCourses(int categoryId, int count);
This way, your services/controller will no longer deal with eager loading, joining, grouping, etc. Instead, they'll delegate to the repository. Remember, eager loading, joining and grouping, etc are querying logic and belongs to your data access layer, not your services or presentation layer.
3- Decoupling your application architecture from persistence frameworks: when you use Entity Framework classes (e.g. DbContext, DbSet, etc) directly in your application, your application is tightly coupled to Entity Framework. If you plan to switch to a different O/RM sometime in the future, or even a newer version of Entity Framework with a different model, you may have to modify many parts of your application and this can lead to new bugs in your application. You can use the repository pattern to decouple your application architecture from persistence frameworks such as Entity Framework. This way, you'll have the freedom to change to a different O/RM with minimal impact on your application.
Check out this video for more details:
https://youtu.be/rtXpYpZdOzM