Generic Repository Pattern With EF Core - Why It Sucks

  Рет қаралды 39,191

Milan Jovanović

Milan Jovanović

Күн бұрын

☄️ Master the Modular Monolith Architecture: bit.ly/3SXlzSt
📌 Accelerate your Clean Architecture skills: bit.ly/3PupkOJ
🚀 Support me on Patreon to access the source code: / milanjovanovic
The generic repository pattern is precisely that - a repository pattern implementation that is generic. You don't benefit from implementing it on top of EF Core. But you do introduce a useless abstraction over EF Core. Specific repositories are a different story, and they're common in DDD. I'll explain in the video how to implement and use the generic repository pattern and why I think it's an anti-pattern.
Join my weekly .NET newsletter:
www.milanjovanovic.tech
Read my Blog here:
www.milanjovanovic.tech/blog
Subscribe for more:
/ @milanjovanovictech
Chapters
0:00 Defining the generic IRepository interface
2:33 Implementing the generic Repository with EF Core
5:00 Configuring generic Repository with DI
5:43 How to use the generic repository pattern
8:34 What I think about generic repositories

Пікірлер: 273
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If you're curious about .NET and software architecture, consider joining my newsletter. I write an email to 14,000+ engineers every Saturday that helps you solve complex engineering concepts with .NET. Subscribe here: www.milanjovanovic.tech/
@indeem1507
@indeem1507 Жыл бұрын
We have a kind of generic repository pattern i quite like at work. There you still implement a repository for each entity, but inherit from the Generic Repository. This way you can always override the generic repository to do entity specific things that the generic repository doesn't provide and you don't have to implement the same methods again and again.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That works better
@ChristofferLund
@ChristofferLund 5 ай бұрын
Same here, combined with unit of work so you have the save changes async not in the repository itself.
@bedirhandincer3448
@bedirhandincer3448 3 ай бұрын
But wouldn't you end up in having too many repositories (per entity) if each of it inherits from a parent class? E.g. imagine if you have repositories that do basic CRUD operations and inherit from a generic repository, you will be left with a lot of potential repositories that has not much to offer since you will also create a service per entity to implement your business logic (using the repository). What are your thoughts @MilanJovanovicTech? How can we avoid this in an architecture like the union one. I understand the principle of reducing code duplication, but it seems to me a bit overkill.
@aaladdin9157
@aaladdin9157 Жыл бұрын
edit: let me clarify by saying what I am talking about below is specific repositories, not generic one. I do completely agree with Milan that having a generic repository alone is a complete waste and just a useless wrapper, but using specific repositories along with a UoW is what I am referring to. Tbh I didn't even realize it's common that people use a generic repo only. ------- Repositories work great if you implement a unitofwork with it, it's a little weird having repositories without a unitofwork for all the reasons you mentioned in the video. The power in repositories in my opinion is re-usability and ease of change/future proofing. What happens if tomorrow EF contains a massive bug or exploit that causes problems, and you need to switch your db querying to a different provider? You will need to re-write a lot of potentially duplicated code across the board, instead of just 1 location. That's the positive side from my perspective, but to each their own. And at the end of the day, there is no one-solution-fits all situation, so do what makes sense for the scenario you are in
@iamjashin
@iamjashin Жыл бұрын
Tbh not really. I've had a huge battle with my team against repositories in my current project which unfortunately I've lost due to links to some MS docs from 2012 (where MS was showing repos). 1. If EF has some massive bug than it will get fixed ASAP. Like really ASAP this stuff is used tens of thousands of projects across the globe. You will have far much easier time upgrading the EF Package than rewriting your repositories. Which leaves us with only other valid scenario which is changing ORMs and how likely are you to do that. 2. Also if we are using ORM most likely we are also going some kind of DDD. That means you should only use EF to either retrieve aggregates which are (should) be build using the same method or to make a non tracking query to database. In second scenario what you end up doing is writing a query against the Quarriable which you may need to rewrite in case of an ORM Change.
@aaladdin9157
@aaladdin9157 Жыл бұрын
EF bugs etc was just an example, there could be many reasons causing you to switch out your provider or ORM or whatever you happen to be using. One major thing I can think of is consulting work for example... If let's say you used dapper when you implemented the project, but after handing it off to your customer, their team doesn't like dapper for some reason and they want to use something else. Having a repo in this case makes things much easier to swap out, without risking changing other pieces of code that really don't need changed. The biggest thing here is code duplication/separation. in the chance you need to switch something out, and risk changing code logic that you don't really need to change, when all you really want is to update how you perform a database query. Even if you were to not use a repo pattern, and let's say you create some kind of a factory for your queries to avoid duplication, you're still basically implementing a repo pattern here, nothing's really changed. But like I said, I am NOT against not using repos, there are other drawbacks to using repos, I just don't think the given example is realistic in terms of an implementation without a UoW, which in my opinion is required for a proper repo implementation
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
The repository pattern won't save you from a DB provider rewrite...
@if07012
@if07012 Жыл бұрын
Usually, I'm using the Generic repository as a base class, I'm not exposing the AsQueryrable as public. so What I do in your case is I create one Method in orderRepository to get a single item, and in the implementation, I use a Generic repository, but in OrderRepositoy we only see the Insert & Get Single Item, so in my perception, we can't use a generic repository like that, expose all method but it depends on how you design your structure code. like @A alddin said the biggest concern for me is the duplication/separation code, so if you need fast you can work directly in EFContext, but if you need maintenance the code, and in the future maybe you need to adjust the method to do a performance, you can re-write the single item use like (dapper/native command) and in all logic will be changes
@real_taiwopeter
@real_taiwopeter 5 ай бұрын
I started learning about the Repository pattern design last week and this video put more light on do's and don'ts. Thank you. I also enjoy your newsletters. although some may seem slightly advanced to me, they motivate me to expand my knowledge base.
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
You're very welcome!
@franciscovilches6839
@franciscovilches6839 Жыл бұрын
Hi Milan nice video. If using specific repos, would you still use UnitOfWork to save changes? Or would each repo be in charge of saving its own changes. Reason I ask: just wondering how you'd use 2 or more specific repos under one single transaction. Ps, I agree with you, it might be a bit unorthodox but using ef core directly is way more pragmatic, and unit/integration testing with ef core is a breeze these days anyway.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yes, I'd use UnitOfWork in that case
@rustamhajiyev
@rustamhajiyev Жыл бұрын
Even if you're tempted to use generic repository to reduce duplication, please don't. I've been this path, it doesn't lead to a bright future of the app. I have spoken 😃
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I couldn't agree more
@carmineos
@carmineos Жыл бұрын
I'd like to know more about this, I currently use it as abstract base class with virtual methods which then typed repositories inherit from
@kimfom
@kimfom Жыл бұрын
yeah me too, this isn’t how I implement generic repository, when I have several derived classes I implement unit of work to take care of the transaction
@phugia963
@phugia963 Жыл бұрын
@@kimfom same idea here, the implementation in video seems weird enough. Not creating concrete derived repository class inherits form the GenericRepository make it mostly impossible to write any specific query related to that repository without uselessly expose IQueryable type from the repository
@Forshen
@Forshen 11 ай бұрын
@@carmineos same, works perfect.
@xskyaflake
@xskyaflake Жыл бұрын
Add UnitOfWork on top of it and you are fine. It depends how you implement this, and while your example shows that that example is weird to work with (it does work however), it can be adjusted and further improved. That's how building software (and architecture) works.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
There's no way to make this work 😅 Either go the Specific repository route, or just use EF Core
@anvogel99
@anvogel99 Жыл бұрын
@@MilanJovanovicTech Generic repos are totally fine from my experience. It can look like: _repoA.Add(a); _repoB.Delete(b); _unitOfWork.Save();
@xskyaflake
@xskyaflake Жыл бұрын
@@anvogel99 exactly like this
@xskyaflake
@xskyaflake Жыл бұрын
@@MilanJovanovicTech well.. A lot of projects use a unit of work, its pretty common. Its easy to combine with the aggregate pattern for example
@yigitgnc
@yigitgnc 5 ай бұрын
​@@anvogel99 why not ? efCorecontext.Set().add efCoreContext.Set().add and call the save in Unit of work, or you can combine all in a manager class which is a unit of work. efcore eb context already provides a very powerfull generic implementation and a perfect lambda query builder. why should I wrap that perfect wrapper again
@emreteoman1564
@emreteoman1564 Жыл бұрын
Totally agree with you. I wrote an article 2 years ago on Medium "Combining repository pattern and unit of work using EntityFramework Core"
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Can you add a link?
@Guillen8606
@Guillen8606 Жыл бұрын
I have worked in projects with already existing databases and usinng the repository pattern saved a lot of time and code. It's not the first way to go for coding but I believe it has it's purposes when needed.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Database-first is a good argument for using it
@mohamed-hassan-
@mohamed-hassan- Жыл бұрын
Interesting. I've used it in a few projects I've worked on but not just this implementation; instead, I've used it as the base repository for every repository I've created, and then implemented the unit of work pattern to wrap the savechanges method with it.. is that ok?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's all right!
@emanueltenca8368
@emanueltenca8368 9 ай бұрын
Wonderful to find this video, finally someone with common sense and an explanation straight to the point. Thank you!!!
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
I'm glad you enjoyed it, Emanuel :)
@sixmund35
@sixmund35 Жыл бұрын
Generic repository in my previous project are there to DRY the code. It contains functions for general crud. But it is the abstract class. It is inherited by specific-repositories. So all specific-repositories will have all simple methods without copy-paste the code.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I've seen that idea float around, I might explore it in another video
@pdevito
@pdevito Жыл бұрын
Eh, I’ve found a generic very useful as a base inheritance for the specific repo implementations. Keeps a consistent foundation and behavior that can be cleanly overridden when needed for a particular repo implementation. Also reduces boilerplate.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
But what's the value of a generic base class in a specific repo vs. just using EF Core?
@pdevito
@pdevito Жыл бұрын
@@MilanJovanovicTech the specific repo inherits from the generic to reduce boilerplate and keep a base consistency that can be overridden when needed. The reason I don’t use dbcontext directly is mostly for testing, but also for consistency of use as mentioned before and other benefits that you get out of a repo.
@ronaldabellano5643
@ronaldabellano5643 Жыл бұрын
@@pdevito testability is important, I was agreeing in the video but I remember testing.
@ramytawfik9168
@ramytawfik9168 Жыл бұрын
Hello Milan, I have a question please. Why Insert/Update/Delete methods are made sync not async ?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Because they don't call the database
@shkelqimhaxha3985
@shkelqimhaxha3985 Жыл бұрын
Totally agree. It is just a wrapper around an already perfect wrapper like ef core is. Anyway I like using repository pattern and depending on abstractions. In the future you might need to change infrastructure, like for example move to dapper or to any other ORM, so sometimes it can be useful
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's not really changing infrastructure. Just changing data access mechanism.
@shkelqimhaxha3985
@shkelqimhaxha3985 Жыл бұрын
@@MilanJovanovicTech yep, that's what I meant
@ShibaCat
@ShibaCat 7 ай бұрын
I read some article talk about that, and I like a words:( avoid abstraction of abstraction )
@flobuilds
@flobuilds Жыл бұрын
If you implement the unit of work than its great again. And you can also implement a repo for all Entities that inherits from the base repo class and specifies the Entity type directly. With this approach you have your repo base methods like add, update, delete and get for example behind your base class and you can keep your Implementation of the e.g. Order Repo clean and add only specific methods to this class. Also what i do is get the db set of the specified entity in the base repo and than you are locked only with the specified set and can't do anything else.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why not just use EF Core at that point since it offers all of that without an abstraction?
@flobuilds
@flobuilds Жыл бұрын
@@MilanJovanovicTech because i want to keep the application as clean as possible. Im also starting to implement ddd as much as possible and this will also help to keep the repos more clean. I use the repos to fully separate the logic. But i have a question for ddd. How to implement aggregates and all this stuff when you work with lists in lists and so on. I have a big entity with many lists in it and other props and many other entities
@svorskemattias
@svorskemattias Жыл бұрын
I guess because we've learned about the importance of inversion of control, clean architecture, interface segregation etc
@csabalajtha3989
@csabalajtha3989 Жыл бұрын
@@flobuilds Let me understand, to keep thing clean you encapsuate a repository (EF) with units of work in an repository with units of work? How is that clean?
@ThrottleScotty
@ThrottleScotty Жыл бұрын
Absolutely agree with you on the "useless wrapper" summary. Been down this path in the past with overzealous architects and its lead to many exceptional cases as app grew in size/complexity.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I also hard to learn that the hard way
@muhammedmmagdi
@muhammedmmagdi Жыл бұрын
So, what's the cleanest way to encapsulate data access logic instead of having this repository? Making a custom repository inherit from the generic one for the custom/complex scenarios will help in this case? And what if we gonna change the db engine, depending on context directly will push us to many changes in many places, right?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Make the repository specific, and only return what you need. Are you ever going to change the DB engine, really?
@muhammedmmagdi
@muhammedmmagdi Жыл бұрын
@@MilanJovanovicTech but making specific repository for each command/query will produce many files beside duplication, what do you think? There're specification pattern, looks like a solution? Yes, I might change db engine, may be use non relational db for reading and relational one for writing, what do you think?
@andersonhansen9542
@andersonhansen9542 Жыл бұрын
Great content! But, for example, you didn't call Dispose() for the DbContext. With the repository, this would be centralized and transparent! In some projects, we actually mix Queries with Dapper with persistence made with EF. Would using a Repository be better in these cases?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
The runtime will take care of disposing
@zaid6357
@zaid6357 Жыл бұрын
Look i used the generic repository but i also created another interface for every entity . So the generic repository for all entity CRUD . But the interface for each entity is inherited from generic repository and i can add more functional actions. You can use unit of work all will work . But is it affects on the memory ??
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How does Generic Repository as a base class differ from just using EF Core?
@zaid6357
@zaid6357 Жыл бұрын
@@MilanJovanovicTech the generic repository is an interface. And in the IServiceCollection i dont use the generic , i use the entity interface
@clebersondot-net
@clebersondot-net Ай бұрын
awesome video! thanks!
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
Glad you enjoyed it!
@NITOAnime
@NITOAnime Жыл бұрын
Isn't the whole point of making repository pattern to make application easily swappable to other communication with database, like pure sql or in memory? Also is it having any benefit for Moq and unit testing?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
There's benefit for unit testing, yes. But is there value in unit testing the DB?
@gordonfreimann
@gordonfreimann Жыл бұрын
doesnt the db context already implement unit of work and repository pattern?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It does
@emwagner
@emwagner Жыл бұрын
I've seen generic repositories using T or TEntity... what's the difference, if any, and which is the best to use for generics?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
No difference
@efimov90
@efimov90 Жыл бұрын
Why if get rid off GetById, GetAll, GetQueryable, and add Specifications to it, and nest it in Unit Of Work? You still need to encapsulate some logick inside repository, but difference between concrete repositories will tend to zero. If make implement them this way will it still sucks?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It will suck less 😁
@herbramos3985
@herbramos3985 8 ай бұрын
Handling the EF calls directly in the Application layer seems to go against the Clean Architecture recommendation to handle persistence in the Infrastructure layer? Your videos are always on-point and informative.
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
It does go against CA directive. I will sometimes be pragmatic and break this constraint.
@asdasdaa7063
@asdasdaa7063 4 ай бұрын
what is the best pattern to use then if not repository pattern? I would love a video on this. Also can you make a video using EF core alongside dapper? Like using them hand in hand, using dapper where ef core lacks and using ef core where it makes sense?
@MilanJovanovicTech
@MilanJovanovicTech 4 ай бұрын
Here you go: kzfaq.info/get/bejne/ht6ojcaFp7_NY2g.html
@vietbacho6308
@vietbacho6308 Жыл бұрын
Hi Milan! What theme color that you are using?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
VS Dark Theme + ReSharper color highlighting
@vietbacho6308
@vietbacho6308 Жыл бұрын
Thank you so much
@ShibaCat
@ShibaCat 7 ай бұрын
And one more reason if I use repo pattern is the solution contains web, api and console , so that I add project reference and share use same repo as well as models and service.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
I like it for testability
@mathewgrabau3870
@mathewgrabau3870 Жыл бұрын
Agreed - I've regretted it each time that I implemented the generic repository pattern. It felt pointless in exactly the way that you described.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You understand!
@florent9555
@florent9555 Ай бұрын
Since you use the customer and order repository, should you not have an unitofwork for the work being done?
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
We would have it, typically
@elpe21
@elpe21 Жыл бұрын
For me, repository ( generic or not ) should not expose IQueryable. The query should be handled within specific repository that inherit from Generic repo... Ie OrderRepository : GenericRepository
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Then you're not doing a generic repository, but a SPECIFIC one. With a generic base class.
@JustPlaneCrazy88s
@JustPlaneCrazy88s Жыл бұрын
I can't like this enough. Including IQueryable would trigger a "Requested Changes" action from me during a PR review. :)
@ardavaztterterian1211
@ardavaztterterian1211 Жыл бұрын
That's the whole point. there is no use of a generic repository if you are going to expose IQueryable. It would be a useless wrapper
@jithin.johnson
@jithin.johnson Жыл бұрын
What if all my repositories have common methods only (0 specific methods). In this case what is a better option than the Generic repository pattern?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If that's the case, why even use a repository. Just use EF
@CodeBallast
@CodeBallast Жыл бұрын
Great content! The problem you are trying to show with generic repositories... wouldn"t the same problem surface if you used a non-generic version? Or, is the point of the problem only the way you register it in the DI container? You could specialise your repository and extend it. interface IMyRepository : IRepository { Task SpecialSearch(...) } class MyRepository : IMyRepository { Task SpecialSearch(...) } Then you would register the IMyRepository and the problem would be resolved. Or, with your original implementation you could open up for the Specification Pattern in a search method.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's a specific repository with a generic base class. Why not just use a Specific repository with EF Core in the implementation?
@denm8822
@denm8822 Жыл бұрын
I always wondered what is the reason of having getall() method of list type, as in real apps there can be millions of rows, and that thing just loads them in memory
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Hopefully you won't use it on a large table 🤣
@sultonbekrakhimov6623
@sultonbekrakhimov6623 Жыл бұрын
I used to use generic repository pattern with reflection dependency injector to be able to easily create API endpoints. It also allows to overwrite it with custom implementation
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How does that work?
@sultonbekrakhimov6623
@sultonbekrakhimov6623 Жыл бұрын
@@MilanJovanovicTech I created extension method for middleware configuration where I retrieve properties form DbContext, iterate over collection and create, register generic repositories. I think it is quite useful as long only EF Core is used as data source provider
@iliashterev38
@iliashterev38 Жыл бұрын
Greetings from Bulgaria. Thank you for your time and efforts to create and share those nice tutorials. Regarding GetAll (either Async or not), this can not be serious. If we have 1 millions rows in the DB with 50 columns, some may be nvarchar(max), i.e. spreading across multiple data pages ... !!??? For the number of columns the same thing follows even for GetById. We usually do not want to pull all columns. Both for load's sake and for security. So here come my next concern. Another good and very common practice is to use intermediate VM classes / entities or as some call it DTO. We do not want unload out whole data table to the end user. So ?? We need mapping. Somehow everyone misses to give examples for that case.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
This is just an argument about generic repositories. In most cases where you are dealing with so much data, you will write very specific queries that will be optimal from a performance standpoint. You can then decide if you want those to be part of the repository.
@williamnwz
@williamnwz Жыл бұрын
Im not sure but when I must create a specific query I use to create a new new class that inherits my basic repository then I create a new interface more specific that inherts my IRepository. then I can create all the query that I want in my specific implementation
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's pretty much the Specific repository pattern, with a base class... At that point why not just use EF Core directly in the Specific repository?
@pilotboba
@pilotboba Жыл бұрын
In c# 8 I think it was we got default interface members so you can put implementations into the Interface you could actually implement all those methods since they are always the same. You could have multiple GetByIds one for Guid and one for Int. Even with generic repositories people are adding methods to do specific queries. For sure returning IQueryable is just not adding value. In my opinion, if you are just looking for a place to "store" your queries because you don't want them in your handlers or endpoints or whatever, there are better ways to do it than to create a repository if you are using EF. The Specification pattern comes to mind, as well as adding Query objects. (basically a class for each query that you might put into a repository). Are you using a repository with DDD and EF?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I like the "specific repository" that just exposes the methods needed, and under the hood uses EF Core in the implementing class
@ram6030
@ram6030 Жыл бұрын
Well I've been using generic repository pattern with unit of work and generic specification pattern (my customized pattern). The issues that you told have all can been handled. Moreover as others have mentioned unit testability increases dramatically with this approach. Also when u need a specific type of query you can create it.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What is the value of unit testing the DB?
@yezinia
@yezinia Жыл бұрын
@@MilanJovanovicTech That is the point with your "anti pattern" rant. You do not test the database, you test the consumers of the repository to do the right stuff and you are directly depending on EF Core, which is a maintenance nightmare (Microsoft doesn't give a F*#! about breaking changes). Not defining an interface that decouples desired behavior from the implementation is just a quick & dirty approach. Inversion of Control gives the need to abstract the behavior your system is depending on, if you do not understand this, then maybe you should not create "tutorial" videos. The next thing that is absolutely not addressed in this video is that it is necessary to separate models. Using database models as domain entities and throwing these entitites out of your controllers as json results is not only bad practice, it is just plain wrong in the long run. Did this years ago like everyone else and ran into really ugly bugs because this pattern enforces an anemic domain model and - and this is the worst part - mutable state wich will be changed by some weird service that only exists to encapsulate business logic. This makes testing quite impossible because you not only have to test the happy path, but also all illegal invariants of an entity. This is just impossible because it will lead into an 2^n problem really quick, depending on the complexity (amount of properties) and variants (data types used for these properties). All in all, i would argue that or mappers like EF Core are the anti patterns, but microsofts marketing and the lack of good education of most developers let's people thing that they are somehow "necessary" and make your life "easier", which they just do not do. They bring more complexity and opaqueness of how your system works. Not separating models, not abstracting behavior you depend on and throwing third party libraries throughout your application will lead to unmaintainable, hard extendable and painful to test big balls of mud to be considered as legacy when being developed. Please do not do this. Do not make each layer depend on some third party library and make your layers clean by using the lowest language levels you can. There will always be some dependency like the programming language or framework, but good software architecture will reduce this to a minimum, making your business application easier to extend, easier to test and agnostic from third parties and their weird roadmaps. This is a win in the long run (believe it or not, software systems will run for a long time, once they are finished), and here I am speaking about decades. And nothing is more painful than making a change in a software that was poorly designed.
@kylekinnear8878
@kylekinnear8878 Жыл бұрын
Its important to note that there are different repository patterns. With DDD, it is specifically for interacting with Aggregates, which is different than general DB queries. I'm considering calling it something like an 'aggregate store,' to distinguish. The general repository pattern is a big problem.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I just called it 'specific repository' and I think that's a fine approach, since you're only exposing aggregates
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
A generic repository seems to simplify a lot at first sight, however, it has a lot of drawbacks in any avdanced scenario. Mostly it doesn't fit non-CRUD operations well, it defies interface segregation, and is inflexible for custom query conditions. The latter I solve by applying the Query Object or the Specification pattern.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'm enjoying more and more using EF Core directly
@pdevito
@pdevito Жыл бұрын
Downside I’ve found to direct EF is testability. Usually leaning on integration tests where it’s moot, but in instances where you do need to use a unit test, dbcontext adds a lot of complexity and pain.
@topmangarbuja8240
@topmangarbuja8240 Жыл бұрын
​@@pdevitoi think you can create and use interface IApplicationDbContext. In that way, it is easy to mock and unit test will be easier to implement.
@gardnerjens
@gardnerjens Жыл бұрын
the Repository interface, makes it easier to mock out the db context?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can also mock EF Core?
@svorskemattias
@svorskemattias Жыл бұрын
Tell us how!
@analisamelojete1966
@analisamelojete1966 5 ай бұрын
Man, I asked myself this very question. Why use a generic, which ends up being a pointless wrapper, truly spot on.
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
I like the repository, but not when it's done like this
@analisamelojete1966
@analisamelojete1966 5 ай бұрын
@@MilanJovanovicTech I just saw it implemented as “clean architecture”, don’t know what to think at this point.
@stunna4498
@stunna4498 Жыл бұрын
tbh i only use repository pattern with unit of work. I would have a global save changes method so instead of having save changes for each repository i would only have one and it would be defined in my Unit Of Work Interface. All my methods of the generic repository inside would only do what they are suposse to do which is add update or remove. The responsiblity of saving those changes would be on my unit of work. So i can add a entity but if i don't call save changes on my unit of work it wouldn't save. Some people dislike this way but for me the responsibility to do this would be my service layer which has the responsiblity to make sure the business rules are applied. But this is me im sure u guys might have different ideas
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
At that point I'd just the specific repository, which is better imo
@jameshancock
@jameshancock Жыл бұрын
The main issue with ef is that it doesn’t allow extending dbsets so that you can properly add or override stuff like security permissions etc. Would love to see your take on securing queries, insert, update, deletes based on claimsprinciple.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Row Level Security? 🤔
@jameshancock
@jameshancock Жыл бұрын
@@MilanJovanovicTech effectively. What we do depending upon perf (and ef 8 likely fixes this with pre compile of queries) is either use a TVF that can be inlined and takes the user id as a parameter for all of our get/lists and have a SecureList extension method on every DbSet. (If it is small we use chained linq where clauses that use predicate builder). We do the same for SecureDelete, SecureInsert and SecureUpdate. In the past that got a wrapper around EF core but now I just use extensions. But it still isn’t a great solution because I want my devs to have to work hard to do any of those things without applying security. It should be the default condition that everything has to go. Through the security checks and rare that they don’t. So I see repository like you outlined as what people do to fix that they can’t extend dbset and inject the ClaimsPrincipal and then override all of the methods and create their own insecure ones that require hoops or at least a Boolean of “yes I really mean bypass security.”
@mohammadsj
@mohammadsj Жыл бұрын
Seems like the only issue you talked about is the GetQueryable. Fo this case I have defined it as Task Get(Expression? filter = null, Func? orderBy = null, string includeProperties = ""); which satisfied almost all cases for me.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Great, now you've got a method that's far more complicated to work with than LINQ
@odumahojorma
@odumahojorma 10 ай бұрын
Tried using the dbcontext directly in a project recently and it was fun till I started writing my unit test it felt like I started wrting more code , I still prefer the write a generic respository with all in include params for joins in queries. Better reuse of code for me than witting specific repository. I mean why repeat myself.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
There isn't a lot of value in unit testing data access logic
@ericblankenburg
@ericblankenburg 10 ай бұрын
EF already implements the repository and unit of work patterns. You don’t need to implement them again on top of what is already there.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Unless you do
@dimsavva
@dimsavva Жыл бұрын
I totally disagree. You can use the UnitOfWork with the Generic repository to call savechanges. You can also create a regular repository and inherit from the generic to avoid repeating code and use that. You can also create a base service class that calls savechanges automatically on dispose and inherit your service class from that. I have my own implementation of the generic repository with UnitOfWork as explained and it has dramatically reduced the logic I write with absolutely no limitations or issues. I think that the problem of your implementation is that it is designed to be just a wrapper around ef core. A decent implementation is super useful and a productivity booster.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If you're using a 'specific repository' that inherits from the generic one, and the generic repository uses EF Core for example. Why not just use EF Core directly at that point inside the 'specific repository'? If you want to reduce repetition, add the generic methods in the DbContext.
@dimsavva
@dimsavva Жыл бұрын
@@MilanJovanovicTech Sure, you could do that. You could find many ways NOT to use a generic repository. Using a generic repo means I don't have to write a specific repo each time when all I need is simple crud on the entity. It's also much cleaner, more readable code. It's also really simple for unit tests. I've also had scenarios where this abstraction allows me to extend certain functionality easily. Sure, everyone has their own preferences and opinions, and you are entitled to your own. I just don't agree with it being labeled an anti-pattern and "Why it sucks" when the advantages are clear, when a complete implementation of the pattern is done. I challenge you to challenge yourself on this, and build your own complete implementation. I enjoy your videos, I just don't agree with you on this.
@CTRLALTF4
@CTRLALTF4 3 ай бұрын
Generic Repository + Unit of Work + Query Specification together make a powerful, fancy, and useful combination.
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
When would you consider it too much?
@CTRLALTF4
@CTRLALTF4 3 ай бұрын
@@MilanJovanovicTech When I choose N-Tire.
@RT-fi7rb
@RT-fi7rb 3 ай бұрын
Why dont you use an async method for insert, update and delete?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Because they don't do anything - just add the entity to the ChangeTracker
@balazs.hideghety
@balazs.hideghety 10 ай бұрын
problems with the repository (applied over EF): 1. you always save UoW (context) and thus, repository save does not make sense 2. repos should handle aggregates, not entities 3. not every aggregate needs add or delete (add is necessary to top-level object, rest can be saved via reachability) so the only benefit of a repo would be some shielding from EF, and it had to be done without introducing ambiguities and without ignoring basic definitions of that repo.
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
It's not perfect, but it can be useful
@gravious
@gravious Жыл бұрын
is this not useful when mixing EFcore and Dapper for instance?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It could be, but you'll run into issues with Identity Map / Change Tracking support
@gibran800
@gibran800 Жыл бұрын
What about combining the generic repo with the specification pattern?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's even more of a mess 😅
@gibran800
@gibran800 Жыл бұрын
Could you elaborate?
@wanderingvista
@wanderingvista Жыл бұрын
One way they are useful is to restrict them to only accept certain types of entities, eg. Aggregate Roots only. What's your view on that?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I get the argument. But not much value in that - you're still the one writing the code 🤔
@svorskemattias
@svorskemattias Жыл бұрын
Me and my colleagues are communicating through code. Someone who is searching for, but not finding a repository for a certain entity, might wonder why, and look up how the entity has been used in other circumstances, and then learn that it is part of an aggregate!
@wanderingvista
@wanderingvista Жыл бұрын
That’s our use case as well indeed. Because we have a guideline to use repo’s rather than dbcontext directly, devs can not easily write entities that shouldn’t be written directly. When they do all the workarounds to do it anyway, then at least it’s easily picked up on in the pull request.
@TanisCZZ
@TanisCZZ Жыл бұрын
100% Agree. And get worse and worse introducing something like IUnitOfWork and IService. And implementation is only passing down and up through layers. Aaand then Big Ball of Mud growing and growing :D
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
IService 🤮🤮🤮
@danilonotsys
@danilonotsys Жыл бұрын
I believe it is valid to use a pattern as a generic repository but only together with a unit of work abstraction as this may ease the use of different database providers (EfCore based or not) and all this should be only in the infrastructure layer. In a DDD project the domain layer should be more technology agnostic and this includes in-memory cache and linq based development both them normally needed in a generic repository
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If you ever try to couple more than one DB provider in a single unit of work, you're in for a world of hurt
@mhar5838
@mhar5838 3 ай бұрын
Hey @MilanJovanovicTech I have an idea that I am eager to know your opinion 1 - create repo interface for every aggregate not every entity but make all of them non-generic 2 - create uow interface too 3 - create one concrete ApplicationDbContext just as you suggested but make it implement all of the above interfaces 4 - inject just needed interfaces (those are relative to aggregates and) to every RequestHandler (or domain sevice objects) in above scenario you don't wrap a thin proxy over entity framework. also your application layer is not dependent to ef core technology. so both schools are covered. what's your opinion?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Do you have a demo implementation?
@mhar5838
@mhar5838 3 ай бұрын
@@MilanJovanovicTech Nop. I tried to test your idea in a new project. it works perfectly and It seems you are right when we are sure we don't need to change ef.core but who knows if a bounded context representing a micro service needs to change its persistance mechanism in future? I think above suggestion covers both parties. application layer is independent of ef core technoogy and we don't also repeat ourseves over and over in every repo or make a generic wrapper repo.
@noelfrancisco5778
@noelfrancisco5778 Жыл бұрын
You may use Specification Pattern together with Repository Pattern, that's the one I am using.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
With or without a generic repository?
@noelfrancisco5778
@noelfrancisco5778 Жыл бұрын
@@MilanJovanovicTech , with Generic Repository. I have the basic CRUD operations and use my services as my unit of work.
@Forshen
@Forshen 11 ай бұрын
For the Generic Repository Pattern (without EF Core, I prefer Query builder like sqlkata), I prefer to have a abstract GenericRepository that implements the base CRUD actions. Every methods should also be virtuel. And Just have a CustomerRepository : GenericRepository. Now the CustomerRepository have all the default methods and you can easily add more methods in the CustomerRepository without creating clutter for other entities/repositories. + if you need to different implementation of the GenericRepository, you can just override it. (afcours, also use interfaces)
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
I'll check out Sqlkata, sounds interesting
@TheCMajor9th
@TheCMajor9th Жыл бұрын
Gen Rep pattern goes well with Unitofwork and as for querable u can make an iquerable method to return an iquerable so i do not understand why its pointless , u dont want teh devs to use the dbcontext anways hence u wrap it and allow only certain methods , also if u need to do generic or custom filtering or some logging of prev and next state in entities if u dont have a gen repo where u will do it ?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What are you adding on top of EF with the wrapper? Nothing... Hence why it's pointless
@ARESCOM_PA
@ARESCOM_PA Жыл бұрын
It's really interesting watching this video after watching the one from Mosh Hamedani (kzfaq.info/get/bejne/qNqIo7yhv8qzqoE.html). However, now I don't know how to proceed since both your videos make sense but they're conflicting. Does it make sense to follow Mosh's method without the generic part?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's a great combo, but I don't like the UoW idea with repository properties. This video was basically an argument against "generic" repository. I also have a "specific" repository video that aligns nicely with the one from Mosh
@ARESCOM_PA
@ARESCOM_PA Жыл бұрын
@@MilanJovanovicTech Thanks. I'll check out your other video. What's wrong with repository properties in UoW?
@prithirajdutta8308
@prithirajdutta8308 2 ай бұрын
How to use SQL Sequence NEXT VALUE FOR .Net API and Entity Framework??? Thanks in advance.
@MilanJovanovicTech
@MilanJovanovicTech 2 ай бұрын
Haven't tried it
@prithirajdutta8308
@prithirajdutta8308 2 ай бұрын
@@MilanJovanovicTech Can you make a video regarding SQL Sequence and EF?
@user-vBqDm4l7wE
@user-vBqDm4l7wE Жыл бұрын
Insert, update and delete should be in the unit of work. Instead of GetOneById it's better to have GetOneAsync(Expression filter) - here you don't need to know the type of the primary key. Regarding the GetAllAsync. I think it shouldn't be a part of a contract and should be implemented as protected method that returns IQueryable in the base repository class which implements IRepository interface
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I like the suggestions!
@user-vBqDm4l7wE
@user-vBqDm4l7wE Жыл бұрын
@@MilanJovanovicTech Thank you 😉
@mahditalebi1770
@mahditalebi1770 Жыл бұрын
Thanks for the video Milan. I think Generic repository with EF Core doesn't make much sense. I actually think repository pattern doesn't make much sense with EF Core either. BUT if you're using Dapper that's a whole different story. Then both repository and generic repository basically become a must have and save you a lot of time and trouble.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How would you do generic repository with Dapper?
@mahditalebi1770
@mahditalebi1770 Жыл бұрын
@@MilanJovanovicTech The repository is pretty much the same as you did in the video without the SaveChanges method. I previously used Dapper.FastCrud to write the methods easier since you can pass in the type of the entity you're querying but it's also possible without FastCrud aswell, it just gets a little bit trickier.
@pioners1001
@pioners1001 2 ай бұрын
I agree that this specific implementation of a generic repository is bad. And the reason for that is that it is not that generic - it is implemented taking EF implementation in mind. Instead, it should be implemented from a Domain perspective. According to DDD repository is like a list, you can add items, update items, remove items, get items by ID, and retrieve all items. You do not have "SaveChanges" or "AsQueriable" from the domain perspective. Some already mentioned that "SaveChanges" should be part of a unit of work. And queries are not the responsibility of the repository. One should implement specific queries separately in some "Loader" or query classes. Then you could optimize those queries in these special classes. For example, this way you could use EF for repositories and Dapper for queries. Also, the benefit of having a repository pattern (not just a generic repository) compared to direct usage of DB context is that you can abstract different databases away. For example, you might use an SQL database with EF for Products and a document database for Orders.
@MilanJovanovicTech
@MilanJovanovicTech 2 ай бұрын
If you search for "generic repository C#/.NET" - something like this pops up. That's why I used it for the example. What you are talking about is something entirely different, which I very much agree with.
@StanZet
@StanZet Жыл бұрын
Hmm.... I wonder did any of you heard about Specification pattern which could be used here instead of that method returning IQueryable? Generic repo has much more sense with it, and Ardalis has quite handy implementation I think...
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I talked about the Specification pattern before
@StanZet
@StanZet Жыл бұрын
@@MilanJovanovicTech need to catch it up :) thanks :)
@ShibaCat
@ShibaCat 7 ай бұрын
I have been struggling on use Repo design pattern or not in long time, I come from 10 years+ .net background and few years work experience in spring boot. My thought is very depend the tech stack used and the project scale. EF is good, it is very good, it come from most of need for CRUD, work with Dapper for very complex SQL is perfect match.
@MilanJovanovicTech
@MilanJovanovicTech 7 ай бұрын
It's a topic that will forever be love/hate for .NET devs
@rhtservicestech
@rhtservicestech Жыл бұрын
4:40 would point out that you defined the SaveChangesAsync, but did not use async and await with that method. I do agree that I don't see a benefit in using a generic repository pattern that you demonstrated here.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Did you even hear the sentence after that? 😅
@rhtservicestech
@rhtservicestech Жыл бұрын
@@MilanJovanovicTech Nah. Visual learner
@nztzn
@nztzn Жыл бұрын
In my opinion Dapper + Repository pattern is very great tool. Just will leave this opinion here :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I'll agree. But you probably don't make it a generic repo with Dapper
@chinthanagunasekara7469
@chinthanagunasekara7469 Жыл бұрын
yes , I also believe this sometimes trying put everything into project without knowing the purpose of it , and UOW also we can ignore. but I've seen some documentation the repository should not be exposed to IQuearyble, who cares :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I've seen worse implementations than this one in the wild
@mateussarmento7692
@mateussarmento7692 9 ай бұрын
I would argue that a DbSet is already a generic repository
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
Yes
@edgeofsanitysevensix
@edgeofsanitysevensix 11 ай бұрын
Agree and disagree with this. If an application is simple and has straight forward crud operations then I agree, this would be an overabstraction and worst and misdirection at best. However, when there is a good deal of business logic involved, I like to move all my db code (including all entity searching) away from the business logic layer. So in this instance would create a generic repository pattern for this along with a unit of work implementation. I don't want my business logic knowing anything about the database specifics and I especially don't want to inject a db context into it. I can also mock the repositories for testing. It's all very well to just say 'Oh just use it directly' but you soon get into messy cross cutting concerns without that abstraction. I definitely would not have DB LINQ code anywhere but a repository. Also, why do you insist in using MediatR for everything? Just curious.
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
There's always extension methods, static classes to solve duplication. I like the benefits I get with MediatR. What else?
@jrgalyen
@jrgalyen Жыл бұрын
Yes! Finally. You have a negative viewpoint about something! Great video too!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Should I talk more about things I disagree with? 🤣
@jadenrogers3133
@jadenrogers3133 Жыл бұрын
The eternal battle... I agree how you did it is flawed. It works very well when used with Steve Smiths Ardalis Specification package, none of that returning an IQueryable. That plus mediatR gives you excellent separation of concerns. When you want to make it hard for a dev to do the wrong thing, don't take an application dependency on ef. If that is not an issue or concern then go for it. It's all trade offs there is no "right" way and everyone should be doing X, do what works best for your team.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I covered specification pattern in another video, no beef with it
@antonmartyniuk
@antonmartyniuk Жыл бұрын
I use a different approach when working with repositories. I encapsulate more logic into my repos: so I would have a single method in my repo that selects a customer and adds an order right into the database. I don't like exposing EF Core to other layers of my code, so my services or CQRS stuff only knows about repositories. That way my application becomes more unit testeable. I use a generic repository but it is abstract. All my real repos inherit from base repo and add any new methods specific to a concrete repository, that way I don't expose IQueryable outside of my repo. Generic repo is not a bad thing in the right hands and can help you get rid of some of the boilerplate code
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That approach makes sense. Maybe I need to record another video?
@antonmartyniuk
@antonmartyniuk Жыл бұрын
@@MilanJovanovicTech maybe
@puzlly
@puzlly 11 ай бұрын
I'll add to the anti-pattern that GetAll method. What happens when someone decides to fetch the whole database with it!!!
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
Things blow up
@PatricSjoeoe
@PatricSjoeoe Жыл бұрын
I think it depends, in bigger application there you maybe will have more generic I think it's great. But much smaller applications can get rid of it. :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Probably the opposite of that makes sense
@RafsanulHasan
@RafsanulHasan Жыл бұрын
I don't completely agree. We can implement specification patterns to avoid exposing IQueryable from repository. But in some cases we also need to expose the IQueryable outside repositories because GraphQL does the paging, filtering, sorting and even projection if we return an IQueryable from GraphQL queries. How about moving those together? Repositories should take a specification in and return an IQueryable instead of specific things like IEnumerable, List of IAsyncEnumerable. Let the caller do that however they need it.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What's the point of Specification then if you'll just return IQueryable? 🤦‍♂️
@adambickford8720
@adambickford8720 Жыл бұрын
This feels more like a poor implementation of SoC than anything. The goal is to isolate business code from the actual persistence mechanism where the repo could be writing to a file or whatever. As soon as you start passing back EF stuff to support 'querying', you've botched the design. No different than if you coupled to an HTTP api to access the verb; abstract that. Your customers almost certainly don't talk about http verbs.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It should. This is how a lot of people do it.
@adambickford8720
@adambickford8720 Жыл бұрын
@@MilanJovanovicTech Yeah, that's just cargo culting. Not ever layer of indirection actually brings value, but they always bring complexity.
@anilkarasahh
@anilkarasahh Жыл бұрын
I am using generic repository pattern on my current project, and I regret that I cannot get rid of it now.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It's never too late to start
@therigbys5693
@therigbys5693 3 ай бұрын
I'm dealing with multiple generic repositories with multiple DbContexts.
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Oh crap
@andreydyachenko1364
@andreydyachenko1364 Жыл бұрын
Generic repository+specification+mapper work fine for common scenaios
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
As if the generic repository wasn't enough, you'd slap a Specification on it? 😅
@z0n_
@z0n_ Жыл бұрын
1. Remove all the methods from IRepository and add one for the specification pattern 2. Add IUnitOfWork interface and implementation + Unit testing is easier + Queries are reusable - Added complexity
@andreydyachenko1364
@andreydyachenko1364 Жыл бұрын
@@z0n_ Or move save changes to IAppDbContext
@usaAlexK
@usaAlexK Жыл бұрын
EF itself implements repository pattern basically.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yup
@ahmedzedan892
@ahmedzedan892 6 ай бұрын
Supposedly you exclude the save changes to be in unit of work and you shouldn't expose the IQueryable from the repository and you should have a repository for every entity that inherits from generic repository and contains the custom methods instead of specifications
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
Supposedly
@RezaulKarim-cq5ft
@RezaulKarim-cq5ft 4 ай бұрын
I think , if u are damn sure that you will never change your database (from sql to nosql let's say) and EF, then using the generic repository pattern is useless. but this is a beautiful pattern to incorporate multiple databases without changing any code from your application layer.
@MilanJovanovicTech
@MilanJovanovicTech 4 ай бұрын
Shouldn't we treat different databases... differently? They're powerful tools. If we abstract too much, we risk losing all these awesome features.
@RezaulKarim-cq5ft
@RezaulKarim-cq5ft 4 ай бұрын
that's true indeed.
@kimfom
@kimfom Жыл бұрын
Repository pattern with multiple derived classes work best with unit of work you know 💁‍♂️
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How so?
@kimfom
@kimfom Жыл бұрын
@@MilanJovanovicTech In your unit of work you should have access to your derived repositories then along with one save changes method and probably implement IDisposable then you add this unit of work to your service container, when you need to persist data you will inject only the unit of work and the service container will resolve the repositories. So you can now just use the unit of work to interact with the two data models and call the unit of work’s save changes… I hope I’m not confusing you 😅
@evadyyc
@evadyyc Жыл бұрын
Yah when our team talks iRepo pattern we include the IUnitOfWork pattern in our meaning… will be nice when copilot just generates all the boilerplate code for us… but do feel it gives us good value for tests when needed. And in theory we could switch out our database layer MSSql/Oracle per customer preference
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What's the value of unit tests for the DB though?
@evadyyc
@evadyyc Жыл бұрын
@@MilanJovanovicTech true, we have a couple… but they would be better written as integration tests to be honest
@arturgabrielyan6332
@arturgabrielyan6332 Жыл бұрын
You didn't implement Generic Repository pattern correctly. For all methods just add predicate, include and enableTracking parameters, to make it flexible for any type of queries - then use it. Also you can use Unit of Works.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Why not just use EF Core if you'll go through all that trouble?
@efaruk
@efaruk 11 ай бұрын
Don't Repeat Yourself, so Generic Repository gives you that and only that and your GetQueryable() should be protected not public...
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
Fair enough
@being_aslam_tiger
@being_aslam_tiger Жыл бұрын
Then what you recommend 😢 if we dont use generic repository pattern.. then which patter i should look for.. please tell me.. 😢 i am junior software developer.. i need your quick suggestions please.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
- EF Core - Specific repository
@being_aslam_tiger
@being_aslam_tiger Жыл бұрын
​@@MilanJovanovicTech thanks ❤
@nicolasundiano8406
@nicolasundiano8406 Жыл бұрын
Generic Repository + Specification Pattern =
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
That's even more of a mess 😅
@nomansoomro7096
@nomansoomro7096 6 ай бұрын
Every infrastructure has its own set of trade-offs. By presenting only one perspective, you are providing a one-sided view that may not capture the full complexity of the situation. Generalizing based on this limited perspective, such as applying it universally to all cases like a generic repository, overlooks the nuanced considerations and potential variations inherent in different scenarios.
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
I have other videos covering different takes on the repository pattern
@user-gu6pn5sv5z
@user-gu6pn5sv5z 10 ай бұрын
But didn't you use a generic repository in your last paid course? 🤔
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
Not how I'm describing it here - check my more recent video about this.
@rufetaliyev9850
@rufetaliyev9850 11 ай бұрын
Oke I get it from this video we shouldnt use repository pattern.
@MilanJovanovicTech
@MilanJovanovicTech 11 ай бұрын
Not really 🤷‍♂️ But the way I implemented is 💩
@rufetaliyev9850
@rufetaliyev9850 11 ай бұрын
@@MilanJovanovicTech Can I use generic repository in microservice?
@KamilRiyas
@KamilRiyas Жыл бұрын
Out of the DDD world, when we are designing applications with basic crud ops with a lot of entities, Generic Repository along with UoW makes life much easier. Eg: You can make changes to the respective repositories and let UoW handle the "Save changes". This is especially helpful when dealing with multiple entities in a single transaction. But yeah... In DDD, generic repository doesn't fit well.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How does Generic Repository as a base class differ from just using EF Core?
@KamilRiyas
@KamilRiyas Жыл бұрын
@@MilanJovanovicTech No difference. In fact, EFCore DbContext uses in-built Unit Of Work. UoW's multi repository operations allows devs to focus more on the domain logics. Again, this opinion supports architecture that is purely CRUD driven with basic verbose APIs. Not DDD.
@asap8426
@asap8426 Жыл бұрын
I'd give u so many thumbs up if I could :D
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You can always create more accounts 🤣
@phugia963
@phugia963 Жыл бұрын
Several things to be discussed here: - First, don't expose IQueryable in the Interface, it's leaky abstraction and create useless wrapper Then how do we fix the issue? Just create a concrete Repository class that inherits BaseRepository: CustomerRepository: GenericRepository , then write the customer specific query logic in the concrete CustomerRepository, and expose the method to Service/ Application layer to call. By doing this we can be flexible enough, while still taking advantages of GenericRepository (save us a lot of code to implement basic repository operators like GetOne, GetAll, AddOne, AddMany, Delete, Update,.... in any specific repository class that inherits it).We could also consider applying Specification pattern if logics inside the concrete repository tend to be repetitive. Although this is a controversial topic, will we be seeing another video of you to correct this video 🤣
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
What's the added value of using GenericRepository vs. using DbContext.Customers?
@phugia963
@phugia963 Жыл бұрын
@@MilanJovanovicTech usually all of benefits from using repository pattern: isolated testability, common abstraction for switching orm/ database, exposing ports for Infrastructure's adapters,... plus the benefits of GenericRepository: saving duplicated CRUD code for any CustomerRepostiory/ UserRepository that inherit it.
@sotsch9280
@sotsch9280 Жыл бұрын
"why not Just use ef Core instead..." .. First: Because not all data comes out of a SQL database, Second: Also Not everyone wants to marry Microsoft products... did you read Clean architecture, or Just talk about IT ;-)? I totally agree with the Point that a generic Repository is no good Idea if Things grow fast. But Sometimes simple CRUD is totally fine when things should be easy and fit in a unified model ("the next scary anti pattern"😂).... Here is my opinion: dont overengineer eveything with ddd paired with clean and keep your scope, Sometimes this is enough! Also thank you for your ideas to this topic❤. Seldomly younger developers care about Software architecture!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
If you advice is don't overengineer, then why not use the simplest tool for the job?
@sotsch9280
@sotsch9280 Жыл бұрын
@@MilanJovanovicTech Good point, but the tool we are talking about is not simple (EF core). As a driver of a car you dont need to understand whats inside the engine. But as a mechanic you have to solve problems that have to do with engines (or replace the whole damin thing :D). If you install an engine that you dont understand, you could get problems you dont understand. To use EF core is easy at first glance, but hard to master in many ways. What i was pointing at with overengineering was the fact that you say "use EF core instead of a (generic) repository because its easier". But then you (as a developer) depend on another external tool thats maybe not necessary because its more complex than just to have a raw and plain repository that writes SQL against a relational DB. I also like to use EF Core + LINQ because it totally fits into modern language of C# (with declarative approach). But its not easier! It requires knowledge about LINQ, you need to read Logs to see if the SQL performs bad, you need to have a clear Model (not a domain model, but a data model that reflects your db table), you need to know about lazy loading and eager loading, and so on.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@sotsch9280 "If you install an engine that you dont understand, you could get problems you dont understand." - the same applies for Database engines 😁 No ORM will save you from having to know SQL and how to use a database.
Saga Pattern For Microservice Architecture With Rebus And RabbitMQ
18:18
Milan Jovanović
Рет қаралды 26 М.
How I Use The Generic Repository Pattern In Clean Architecture
17:15
Milan Jovanović
Рет қаралды 34 М.
아이스크림으로 체감되는 요즘 물가
00:16
진영민yeongmin
Рет қаралды 55 МЛН
Мы никогда не были так напуганы!
00:15
Аришнев
Рет қаралды 6 МЛН
Making Entity Framework Core As Fast As Dapper
13:17
Nick Chapsas
Рет қаралды 83 М.
Visual Studio Code Tips how to edit multiple lines at the same time
2:53
The Unit of Work Design Pattern Explained
12:37
ArjanCodes
Рет қаралды 21 М.
Repository Pattern with C# and Entity Framework, Done Right | Mosh
26:24
Programming with Mosh
Рет қаралды 867 М.
The Beginner's Guide to Clean Architecture
13:19
Milan Jovanović
Рет қаралды 20 М.
Unit of Work in ASP.NET Core
14:57
Raw Coding
Рет қаралды 18 М.
Building .NET 8 Minimal APIs With AWS Lambda and Amazon RDS
15:24
Milan Jovanović
Рет қаралды 21 М.
What Are Your Thoughts on Entity Framework Core vs. Dapper?
21:49
How To Create Generics in C#, Including New Features
38:51
IAmTimCorey
Рет қаралды 42 М.
КРУТОЙ ТЕЛЕФОН
0:16
KINO KAIF
Рет қаралды 5 МЛН
Мой инст: denkiselef. Как забрать телефон через экран.
0:54
Как правильно выключать звук на телефоне?
0:17
Люди.Идеи, общественная организация
Рет қаралды 922 М.
Simple maintenance. #leddisplay #ledscreen #ledwall #ledmodule #ledinstallation
0:19
LED Screen Factory-EagerLED
Рет қаралды 35 МЛН