Get the source code for this video for FREE → the-dotnet-weekly.ck.page/repository Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Actually, the only reason why I prefer to wrap DbContext with Repo abstraction is to limit access to IQueryable. OFC, if we speak about read queries, then I am ok with using db context directly in controller =)
I really like the repository pattern. I usually bundle all of them up as public fields in an service to inject into classes. I also like implementing a basic implentation of IRepository as an abstract class that provides basic crud for entities and inheritors do the queries while the Use Case classes handle transactions. It has worked nice so far 👍
I have moved away from repository pattern over the years. we rather use dbcontext directly. development time is much faster this way. we use SQLite provider for testing.
But remember, the code is much structured and readable when it comes to modification and testing. And in large scale applications, you need to access other services.
i wonder whether "development time is much faster" holds true in the long run e.g. when u want to or have to replace the ORM or the database technology. Just consider .NET framework vs .Net Core vs .Net 6. the huge disadvantages of coupling an application to tight to a particular technology/framework now become obvious in many projects when those try to migrate
we use at least 4 different databases, even if it's not a netflix kind of big application it's still pretty big. efcore just for commands mostly. we have dapper as well. with decent test coverage. code structure and readability is more of something you establish in the team and maintain through PR reviews. EF has been the defacto ORM for .NET, we accepted this is how it is and we do not plan to replace it. If there is such a big transition, it's more likely it will be more than just the ORM code that needs to be replaced.
I wonder how many codebases had to replace efcore with something else. Moving to something else than SQL will require a lot more change then just ORM. Dapper and EfCore can co-exist to provide best of both. What scenario have you faced thus far that made you replace Efcore?
@@fullstackdotnet "if there is such a big transition, it's more likely it will be more than just the ORM code that needs to be replaced." well, if properly abstracted away - e.g. using repository pattern - such a transition would actually be small. that's the whole point - it is not that u cannot replace ORM without repository pattern and similar abstractions it is that it is much easier with those abstractions.
What is yours thoughts about "GetByIdWithCreatorAsync" and "GetByIdWithInvitationsAsync" returns a partial Entity data? Because if I use GetByIdWithCreatorAsync, the response will has empty invitations, and if I pass this result to another context, this new context will presume that this Gathering has not invitations, but it's because the source did not populate this informations. In my opnion, we should ever retrieve fully entity, and when we need a diferent structure, we need to create a DTO to represent this new structure. I'd like to know what is your thougths about this point.
This is also something I struggle with, especially when there are complex business objects whose entire state needs to be known before you can perform an operation. I've seen it suggested elsewhere that instead of partially loading entities you would create different flavours of the same entity under different namespaces. I too would like Milan's thoughts on this.
@@davidm7333 Interesting suggestion with creating different flavors of the entity. My thinking is that Aggregates are for establishing a boundary of data and rules that uphold valid data transitions. If the Aggregates are partially loaded then the rules would allow a different set of transitions than they would on a fully loaded Aggregate. I think in practice methods like these are very common, they violate the idea of an Aggregate, they take advantage of the use-case specifics to partially load the aggregate boundary and only trigger the rules that will work correctly on the partial data. Susceptible to bugs if the aggregate is passed around in other components. I've seen a suggestion that if the Aggregate boundary really needs to be big then lazy loading can be applied, my experience with this technique is minimal. Or really try to split apart the big Aggregate into smaller Aggregates, which I imagine is not an easy task. But speaking from experience, I find that people use Repositories for the Reading side of CQRS and and artificially expand the boundaries.
Indeed, they do return partial data in terms of the Aggregate. But in terms of the current business operation, it contains all of the data that is required. With large objects, it's sometimes more important to be pragmatic than to follow DDD strictly.
Implementing your own Repository pattern can be great if you want that semantic Data Access Layer that is not really CRUD - to all developers, please don't think in terms of CRUD. I even removed my generic version after watching this clip because experience from work tells me they are misused and more or less are CRUD. That is not what Repositories are in DDD. If so, It is better just using EF Core directly. It is after all an implementation of the same pattern.
I have a very large entity with 10+ columns. Is it okay to return a small subset of these columns from the Repository as a DTO or should we always return domain objects from the Repository. If I always return domain objects then SQL queries will unnecessarily fetch all columns. But with a DTO I can get just the required columns.
Hi Milan. Is it OK to return DTO object from the repository method? My repository method executes the Stored Procedure, which uses a dynamic pivot inside. If I return entities it will be too difficult to implement (dynamic pivot query) with LINQ in the Application layer (QueryHandler). Thank you.
You mention querying the database context directly in your query handlers, but that would violate the separation of the application layer from the infrastructure layer in that it then ties directly to the persistance store. Wouldn't it make more sense to encapsulate this in the repository service, then your implementation of the query can still be performant albeit in the infrastructure layer?
What if instead of returning iquerayable the function has some more paramters like expression of orderby,filters,inner joins. If any of that has a value we will add it to iqueryable and return list at last?
@@MilanJovanovicTech but we are injecting the dbContext in the repository right? Should we inject it at command level? If we do so, how are we going to get that opened instance in the repository methods?
Hi Milan, I have one question: Is better to have one method in repository that return the entire entity and then in controller split in many methods for every different dto of the same entity returned or to have one method either in api and repository and then in presentation layer split up the service layer in different methods for every viewmodel/dto needed? Another option would be to not have a repository but directly a service layer that interact directly with dbcontext and return different dtos from different methods to different endpoints controller, is this the better options? Thanks in advance.
That has nothing to do with DDD constraints. More so with Clean Architecture constraints. And yes, it would pollute our query handlers. Is this something we can live with?
Where does this Repository pattern come from? When I look up „Patterns of Enterprise Application Architecture“ by Martin Fowler, it says “A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.” With this in mind, isn’t the thing you showed in this video rather an abstraction around EF’s repository (the DbSet) than a repository itself? The caller does not need to pass the concrete query specification, simplifying it’s I/O call. But the thing you call does not actually translate to SQL queries, or document queries or whatever - that task is still performed by EF’s DbSet. BTW, I don’t use the repository pattern as you’ve shown it in this video. I simply use unit of works (I call them session for convenience) and then simply add a method per database call that I want to perform. If I want to manipulate data, the session also has a SaveChangesAsync method to commit the transaction. It’s somewhat the same as your solution, except that the unit of work and all repository members are defined in one abstraction.
is the _dbContext.Set is the same as if we DbSet TName in the DbContext.cs and then _dbContext.TName.DoSomething() ? EDIT : just read its the same, then you dont put DbSet TName in DbContext.cs when using this approach ?
I’ve seen a lot of talk about using the DbContext directly in queries etc, but nobody seems to describe how you then go about unit testing that class/method. Do you have any insights into that, or do you rely on integration tests to satisfy the testing requirements?
@@MilanJovanovicTech that’s what I thought! 😂. The lack of easy unit testing of direct use of the context is the one thing that keeps me using repositories. I can see the appeal of just using the context though 😁
From my perspective the benefits of the repository pattern clearly outperform possible disadvantages. Just the fact that the application logic remains strictly independent from any concrete ORM or even database technology is kinda "killer argument". The additional abstraction and the few amount of additional lines of code I wouldn't really consider as an issue. Another great video 👍😉
Here's an example: github.com/m-jovanovic/event-reminder/blob/main/EventReminder.Persistence/EventReminderDbContext.cs Notice that the DbContext implements IUnitOfWork
I am enjoying your videos Milan. They are 🔥🔥🔥. Allow me comment about some things. 1. Why aren’t you using AsNoTracking when reading the Db? 2. Why are you using mock interfaces? I read that Microsoft recommends using attributes to using mock interfaces. They claimed that attributes may hurt performance somehow but they are a better approach. Thank you
@@MilanJovanovicTech Thanks for the reply. I mean in those 2 methods that query the Db. Is tracking changes needed? Maybe I used a wrong term. I mean empty interfaces. Why not just create a custom attribute and decorate your classes that for example are Aggregate roots?
Yes, I have that planned for some point in 2023. I want my channel to mature more, and myself to become better at creating video content before I take up creating a course. What topics would you be interested in?
Can see Application prj (layer?), Domain prj, Infrastructure prj..and Persistence prj which contains the Repo implementations. From a Clean Arch perspective, is Persistence prj in fact part of Infrastructure?
Hi Milan! First of all, thank you for another amazing content. I´m trying to use FindAsync(id) on my GetById method but it´s always returning null. Of course, the Id is correct and the data exists in the database. I´m just not figuring out what exactly is happening. This behavior also occurs when I try to use FirstOrDefaultAsync(). What am I missing? By the way... - I´m using .NET 6 and EF Core 6. - My repositories implements the IRepository which contains all the common CRUD operations. - Basically, my flow is Controller > Service > Repository. - In my entities, the Id property is a GUID. - My repo method GetAllAsync() works like a charm. public async Task GetByIdAsync(Guid id) => await this._dbContext.Set().FindAsync(id); Thank you!
Hey Milan, I personally like your video, but to talk about this video, you could explain the overall folder structure and explain the code a little bit of all the .cs files you added in the solution that will help a lot Thanks in advance !
Hi Milan, Thanks for this great video. I have come across below implementation in projects i have worked-on. instead of adding IGathering or IAttendee , i see something like this var gatheringRepo = _unitOfWork.Repository(); gatheringRepo.Add(gathering); var saveResult = await _unitOfWork.CompleteAsync(); is this better way of implementation ?
Yes. That's just another implementation of the same pattern. Somehow, giving access to repositories only via unit of work, visually enforce the idea that every entity that you will work with extracted from repositories are related with the unit of work, that is the session you are sharing. And I agree with this approach. However, behind the scene there is always the dbContext injected into repositories and unit of work, so there's no technical difference between these two approaches.
@@marcociaschini4616 But in the Milan’s example, lets say in real world projects we may have more than 2 repositories, injecting each of them in UOW would make class ugly. It needs to change whenever we introduce new repo. What’s your suggestion?
@@JOHNSONLOBOlobojony in real world you will deal with many repositories for sure. But it's even worse: some repositories will work with one db context, some others with a different one and so on. Unit of work must remains your unique transactional business session hiding the various db contexts involved, and committing everything once for all. However, the problem of polluting unit of work injecting many repos it's easy solved. You could register each repo one by one in the IoC engine and injecting an array of them in the constructor of the unit of work. Then you could provide a simple GetRepository() in the unit of work.
Hi Milan! One question, do you know how can I create a solution using multilayers archittecture with EF and without referencing the DAO layer in the Web layer? Because I dont want to make that reference but is necessary for using EF
Milan, thank you for the video! I have a question about architecture. For example, I have 2 aggregate Roots (AR): "Company Customer" and "Individual Customer" which depended from abstract Customer class. So, as I understand I need to have 2 repository interfaces for each AR which will return appropriate ARs objects. But if I need to get all Customers, what should I do? In one hand I can use two requests (1 to get all Company Customers and 1 to get all Individual Customers) and combine them - it looks ugly. In other hand I can move repository interfaces to Infrastructure layer, create some common repository and CustomerDalDto - but here my application layer will be dependent from infrastructure layer... How to solve such task?
I found some definition of Repository in DDD by Edward Hieatt and Rob Mee that repository "mediates between the domain and data mapping layers using a collection like interface for accessing domain objects". And here I understand some nice idea, that in Commands (CQRS) I defenetly need to save consistency boundary and some Domain rules. Cause of that I need to use repositories. But in Queries I don't need consistency boundary, I just need only data in some DTO variant. So, in my example I just need to use Query to get all Customers via dbContext in that Query. Yes, Application layer will depends from Infrastructure. Is it a bad idea or some kind of compromise?)))
@@MilanJovanovicTech Hi Milan, in the real project, which one do you prefer? place DBContext in the application layer or many common repositories for complex query? Any advice?
One thing that slightly bothers me is that you abstracted the EFCore implementation away with a repository to then leak it back into your domain. In other words your db model is a straight copy of your domain entity so that tells me that you either add something funny in your domain entity to make it work with efcore(leak) or your models arent as complex yet and you will walk against that problem sooner or later.
I do neither of the two things, actually. I model my Domain using DDD principles. It's when it comes to configuring EF that I make adjustments to fit everything into a relational model.
@@donnyroufs551 No, that's conforming to EF Core. You want to avoid that at all costs. Design the domain model regardless of the peristence mechanism you are using. You can configure how you map the domain model to the database with EF Fluent configurations. Perhaps I should make a video about this?
@@MilanJovanovicTech but thats my point, I dont see how thats possible without walking against problems when straight up returning the db model from your repo?
Hi Milan! What design pattern do you know for SocketListener and Client (example, console apps and client server communications)? It is very difficult for me to make a server (listener) with disacoupling, and link the socket to a logged user. Where can I find information about this? How can I think a P2P solution for example or any solution in this concept?
@@MilanJovanovicTech I don't know any other way to contact you. You are talking about repository pattern and as you don't have any video of TcpListener and the best practices. So, I decided to write my question here. =)
Hello good afternoon, I loved your video, thanks for sharing knowledge. I wanted to ask you if it is possible for you to make a video by applying it to windows forms. I can't figure out how to apply it. From already thank you very much. Greetings from Argentina
I have a question: Why don't you define the methods 'Add' and 'Remove' in the repository asynchronous just like the query methods? Thank you very much.
Hi, Milan. Thank you for yet another awesome video! I have learnt a lot from all of your videos! I saw you always use dbContext.Set() method instead of dbContext.Entity, there are a difference between them I don't know or they are doing the same thing?
Hello MilanJovanovic Tetch I really like your content, could you make a video on how to use C# entity framework 4 for a good project architecture, using msql or sql server?
Hello, Milan :) I like all your videos! Congratulations for making understanding complex subjects in general really simple to be put to practice, mostly. Do you have some content in which you explain the Unit of Work Pattern and how you would implement it by using EFCore and the IUnitOfWork interface? Any pointers? I would very much like to hear it from you! Best regards and keep rockin'!
Yes please show how you do the EF changes (add,delete,update) using your Unit of Work. It would also be good if you show how to use EF without using API. That is say a Windows Services App using EF that gets a IEnumerable. Then make changes to the DTOObj, and then apply this change back to EF without errors of it's being track, .... Plenty on doing this but all use APIs. Nothing on using EF without API updates.
Am Pretty New to Patterns. Why is the ICommand different in this video and CQRS Dosent Have to be complicated? Could you shed more light as what I see is both seem to be CQRS Pattern
Maybe there is better video to ask about that but whatever 😊 Why usually implementation of unit of work is not tightly coupled to repositories, I mean that (for now let’s forget about mediator pattern) would it be more practical to access repo from uow? //just a sample using(uow = unitOfWorkFactoryX.Create()){ uow.SomeRepository.Save(…) or uow.Repository.Save } Especially when there is more than one context, asking hypothetically 😅
@@MilanJovanovicTech Same old one xD with a newer solution. IMO there are 2 benefits of using the repository pattern along with EF core, easier testability, and query encapsulation. as you correctly said EF context is a combination of repository and unit of work so if we can solve the two problems that I mentioned we don't need a repository pattern. test -> it is completely possible and easy (with a small test framework) to mock and test the DbSets directly. encapsulation -> usually and most of the time it is not necessary to encapsulate queries that usually we only use once but for those queries that we need to encapsulate and reuse we can achieve the same results using a simple static class and some extensions. I think there is a tradeoff between clean coding and complexity when we talk about repository pattern and EF, I personally believe the repository complexity and an extra layer don't help at all. Although, In my experience, it is really clean to have repositories in small projects or microservice projects but having a big code base like a monolithic project … repositories are a real pain and sometimes really messy.
Get the source code for this video for FREE → the-dotnet-weekly.ck.page/repository
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Hi Milan, can you share the folder structure of DDD pattern in video or newsletter
@@MTSightseeing Yeah, that's a great idea actually!
Can you provide github url ?
Actually, the only reason why I prefer to wrap DbContext with Repo abstraction is to limit access to IQueryable. OFC, if we speak about read queries, then I am ok with using db context directly in controller =)
True, that can be an advantage also!
Or use DBSet intead genericRepository class
why limiting access to IQueryable ?
@@ramytawfik9168 People tend to abuse it by creating ad-hoc queries.
I really like the repository pattern. I usually bundle all of them up as public fields in an service to inject into classes.
I also like implementing a basic implentation of IRepository as an abstract class that provides basic crud for entities and inheritors do the queries while the Use Case classes handle transactions. It has worked nice so far 👍
Then you may want to skip my recent video on generic repositories 🤣
Cool tutorial. By the way, background question is... Horde or Alliance? :D
Horde 💪 What about you?
@@MilanJovanovicTech No other choice than strength and honor ;)
Awesome Milan!!!
Thank you, glad you liked it :)
you are making me a better programmer, really. Thank you s2
Wow, I love it when I hear that. Thanks for making my day better :)
I have moved away from repository pattern over the years. we rather use dbcontext directly. development time is much faster this way. we use SQLite provider for testing.
But remember, the code is much structured and readable when it comes to modification and testing. And in large scale applications, you need to access other services.
i wonder whether "development time is much faster" holds true in the long run e.g. when u want to or have to replace the ORM or the database technology. Just consider .NET framework vs .Net Core vs .Net 6. the huge disadvantages of coupling an application to tight to a particular technology/framework now become obvious in many projects when those try to migrate
we use at least 4 different databases, even if it's not a netflix kind of big application it's still pretty big. efcore just for commands mostly. we have dapper as well. with decent test coverage. code structure and readability is more of something you establish in the team and maintain through PR reviews. EF has been the defacto ORM for .NET, we accepted this is how it is and we do not plan to replace it. If there is such a big transition, it's more likely it will be more than just the ORM code that needs to be replaced.
I wonder how many codebases had to replace efcore with something else. Moving to something else than SQL will require a lot more change then just ORM. Dapper and EfCore can co-exist to provide best of both. What scenario have you faced thus far that made you replace Efcore?
@@fullstackdotnet "if there is such a big transition, it's more likely it will be more than just the ORM code that needs to be replaced." well, if properly abstracted away - e.g. using repository pattern - such a transition would actually be small. that's the whole point - it is not that u cannot replace ORM without repository pattern and similar abstractions it is that it is much easier with those abstractions.
What is yours thoughts about "GetByIdWithCreatorAsync" and "GetByIdWithInvitationsAsync" returns a partial Entity data? Because if I use GetByIdWithCreatorAsync, the response will has empty invitations, and if I pass this result to another context, this new context will presume that this Gathering has not invitations, but it's because the source did not populate this informations.
In my opnion, we should ever retrieve fully entity, and when we need a diferent structure, we need to create a DTO to represent this new structure.
I'd like to know what is your thougths about this point.
This is also something I struggle with, especially when there are complex business objects whose entire state needs to be known before you can perform an operation. I've seen it suggested elsewhere that instead of partially loading entities you would create different flavours of the same entity under different namespaces. I too would like Milan's thoughts on this.
Yeah, you are totally right
@@davidm7333 Interesting suggestion with creating different flavors of the entity.
My thinking is that Aggregates are for establishing a boundary of data and rules that uphold valid data transitions.
If the Aggregates are partially loaded then the rules would allow a different set of transitions than they would on a fully loaded Aggregate.
I think in practice methods like these are very common, they violate the idea of an Aggregate, they take advantage of the use-case specifics to partially load the aggregate boundary and only trigger the rules that will work correctly on the partial data. Susceptible to bugs if the aggregate is passed around in other components.
I've seen a suggestion that if the Aggregate boundary really needs to be big then lazy loading can be applied, my experience with this technique is minimal.
Or really try to split apart the big Aggregate into smaller Aggregates, which I imagine is not an easy task.
But speaking from experience, I find that people use Repositories for the Reading side of CQRS and and artificially expand the boundaries.
Indeed, they do return partial data in terms of the Aggregate. But in terms of the current business operation, it contains all of the data that is required.
With large objects, it's sometimes more important to be pragmatic than to follow DDD strictly.
@@MilanJovanovicTech thanks
Best Repository Pattern video I've seen in a while. Well done!
Thank you so much, Stefan!
Implementing your own Repository pattern can be great if you want that semantic Data Access Layer that is not really CRUD - to all developers, please don't think in terms of CRUD.
I even removed my generic version after watching this clip because experience from work tells me they are misused and more or less are CRUD. That is not what Repositories are in DDD. If so, It is better just using EF Core directly. It is after all an implementation of the same pattern.
Very well said Marina :)
I have a very large entity with 10+ columns. Is it okay to return a small subset of these columns from the Repository as a DTO or should we always return domain objects from the Repository. If I always return domain objects then SQL queries will unnecessarily fetch all columns. But with a DTO I can get just the required columns.
For commands -> fetch the entire aggregate
For queries -> fetch only what you need
Hello , Milan
Nice video , expecting the Generic Repository pattern soon.
I'm not sure about that, since I don't like the generic repository pattern 😅
You don’t like may be because it needs specification pattern to rescue it , at least what I have seen in case of EF or any other reason.
@@MilanJovanovicTech Can you share the reason why you don't like Generic repository pattern.
Hi Milan. Is it OK to return DTO object from the repository method? My repository method executes the Stored Procedure, which uses a dynamic pivot inside. If I return entities it will be too difficult to implement (dynamic pivot query) with LINQ in the Application layer (QueryHandler). Thank you.
That's perfectly acceptable
I've been thinking a lot about how to prevent other developers from coding against constraints. Loved the unit test/reflection idea.
Sometimes it's not worth the effort. People will just break things for no reason. 🤷♂️
@@MilanJovanovicTech sadly true
You mention querying the database context directly in your query handlers, but that would violate the separation of the application layer from the infrastructure layer in that it then ties directly to the persistance store. Wouldn't it make more sense to encapsulate this in the repository service, then your implementation of the query can still be performant albeit in the infrastructure layer?
It would, but I'm just listing it as a viable alternative. What do you think?
What if instead of returning iquerayable the function has some more paramters like expression of orderby,filters,inner joins.
If any of that has a value we will add it to iqueryable and return list at last?
What would be the benefit?
We can have a generic method for incase of we hve joins,filters and all
How do we define BEGIN a DB transaction for operations happening across repositories in the Command layer? Assuminig we are using EF Core.
Start one with EF before you call repositories
@@MilanJovanovicTech but we are injecting the dbContext in the repository right? Should we inject it at command level? If we do so, how are we going to get that opened instance in the repository methods?
Hi Milan, I have one question:
Is better to have one method in repository that return the entire entity and then in controller split in many methods for every different dto of the same entity returned or to have one method either in api and repository and then in presentation layer split up the service layer in different methods for every viewmodel/dto needed?
Another option would be to not have a repository but directly a service layer that interact directly with dbcontext and return different dtos from different methods to different endpoints controller, is this the better options?
Thanks in advance.
I like the second option better for queries
Love this quality DDD content, is small nuggets, well explained.... Great Channel
Thanks a lot! 😁
Waiting for your next esp. on how to apply Specification Pattern.
Coming right up 😁
Hi Milan! When you are injecting the dbcontext in your queries is this not breaking the ddd constraints?
That has nothing to do with DDD constraints. More so with Clean Architecture constraints. And yes, it would pollute our query handlers. Is this something we can live with?
Thank you Milan!
You're welcome :)
Interesting! 🙌
Wow, you're quick! I'm glad you liked it
can you please make a video telling us why you do not use repository pattern in Queries in CQRS pattern ?
Planning recording for this week :)
@@MilanJovanovicTech thanks bro
Where does this Repository pattern come from? When I look up „Patterns of Enterprise Application Architecture“ by Martin Fowler, it says “A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.”
With this in mind, isn’t the thing you showed in this video rather an abstraction around EF’s repository (the DbSet) than a repository itself? The caller does not need to pass the concrete query specification, simplifying it’s I/O call. But the thing you call does not actually translate to SQL queries, or document queries or whatever - that task is still performed by EF’s DbSet.
BTW, I don’t use the repository pattern as you’ve shown it in this video. I simply use unit of works (I call them session for convenience) and then simply add a method per database call that I want to perform. If I want to manipulate data, the session also has a SaveChangesAsync method to commit the transaction. It’s somewhat the same as your solution, except that the unit of work and all repository members are defined in one abstraction.
Do you have an example somewhere for the implementation you're using?
@@MilanJovanovicTech Yes, I have. But I think this comment would not pass UA-cam's SPAM filter if I put a link in it. I will contact you on Twitter.
is the _dbContext.Set is the same as if we DbSet TName in the DbContext.cs and then _dbContext.TName.DoSomething() ? EDIT : just read its the same, then you dont put DbSet TName in DbContext.cs when using this approach ?
Yes, it's the same
I’ve seen a lot of talk about using the DbContext directly in queries etc, but nobody seems to describe how you then go about unit testing that class/method. Do you have any insights into that, or do you rely on integration tests to satisfy the testing requirements?
They don't talk about it because it's a mess to unit test 🤣
Your best bet would be an in-memory database for unit testing
@@MilanJovanovicTech that’s what I thought! 😂. The lack of easy unit testing of direct use of the context is the one thing that keeps me using repositories. I can see the appeal of just using the context though 😁
From my perspective the benefits of the repository pattern clearly outperform possible disadvantages. Just the fact that the application logic remains strictly independent from
any concrete ORM or even database technology is kinda "killer argument". The additional abstraction and the few amount of additional lines of code I wouldn't really consider as an issue.
Another great video 👍😉
Couldn't agree with you more! 🔥
Milan can we see the unit of work class?
Here's an example: github.com/m-jovanovic/event-reminder/blob/main/EventReminder.Persistence/EventReminderDbContext.cs
Notice that the DbContext implements IUnitOfWork
@@MilanJovanovicTech Thanks Milan 👍
Hi Milan thanks for great videos. How do I use the repository pattern with out entity framework.
What would be your ORM or data access library? You just use that in the repository implementation
@@MilanJovanovicTech I use the Microsoft.PowerPlatform.Dataverse.Client SDK to interact with database
Great Content
Thank you!
Thank you Milan
You're welcome :)
I am enjoying your videos Milan. They are 🔥🔥🔥. Allow me comment about some things.
1. Why aren’t you using AsNoTracking when reading the Db?
2. Why are you using mock interfaces? I read that Microsoft recommends using attributes to using mock interfaces. They claimed that attributes may hurt performance somehow but they are a better approach. Thank you
1. I want to track changes
2. Where am I using "mock" interfaces?
@@MilanJovanovicTech Thanks for the reply. I mean in those 2 methods that query the Db. Is tracking changes needed?
Maybe I used a wrong term. I mean empty interfaces. Why not just create a custom attribute and decorate your classes that for example are Aggregate roots?
Do you guys have a sample repository? I cant find one online
I share the code with my Patreons. However, you can find some similar examples on my GitHub profile
Great video Milan. I was wondering if u had a plan of making a course in the future?
Yes, I have that planned for some point in 2023. I want my channel to mature more, and myself to become better at creating video content before I take up creating a course.
What topics would you be interested in?
Can see Application prj (layer?), Domain prj, Infrastructure prj..and Persistence prj which contains the Repo implementations. From a Clean Arch perspective, is Persistence prj in fact part of Infrastructure?
Got some samples here: github.com/m-jovanovic
Hi Milan! First of all, thank you for another amazing content.
I´m trying to use FindAsync(id) on my GetById method but it´s always returning null. Of course, the Id is correct and the data exists in the database. I´m just not figuring out what exactly is happening. This behavior also occurs when I try to use FirstOrDefaultAsync(). What am I missing?
By the way...
- I´m using .NET 6 and EF Core 6.
- My repositories implements the IRepository which contains all the common CRUD operations.
- Basically, my flow is Controller > Service > Repository.
- In my entities, the Id property is a GUID.
- My repo method GetAllAsync() works like a charm.
public async Task GetByIdAsync(Guid id) => await this._dbContext.Set().FindAsync(id);
Thank you!
Should work - what's the query generated for this LINQ?
Hey Milan, I personally like your video, but to talk about this video, you could explain the overall folder structure and explain the code a little bit of all the .cs files you added in the solution that will help a lot
Thanks in advance !
Thanks for the idea!
Hi Milan, Thanks for this great video. I have come across below implementation in projects i have worked-on. instead of adding IGathering or IAttendee , i see something like this var gatheringRepo = _unitOfWork.Repository();
gatheringRepo.Add(gathering);
var saveResult = await _unitOfWork.CompleteAsync();
is this better way of implementation ?
Yes. That's just another implementation of the same pattern. Somehow, giving access to repositories only via unit of work, visually enforce the idea that every entity that you will work with extracted from repositories are related with the unit of work, that is the session you are sharing. And I agree with this approach.
However, behind the scene there is always the dbContext injected into repositories and unit of work, so there's no technical difference between these two approaches.
@@marcociaschini4616 But in the Milan’s example, lets say in real world projects we may have more than 2 repositories, injecting each of them in UOW would make class ugly. It needs to change whenever we introduce new repo. What’s your suggestion?
Which would be easier to test?
@@JOHNSONLOBOlobojony in real world you will deal with many repositories for sure. But it's even worse: some repositories will work with one db context, some others with a different one and so on.
Unit of work must remains your unique transactional business session hiding the various db contexts involved, and committing everything once for all.
However, the problem of polluting unit of work injecting many repos it's easy solved. You could register each repo one by one in the IoC engine and injecting an array of them in the constructor of the unit of work.
Then you could provide a simple GetRepository() in the unit of work.
Hi Milan! One question, do you know how can I create a solution using multilayers archittecture with EF and without referencing the DAO layer in the Web layer? Because I dont want to make that reference but is necessary for using EF
Why don't you want to make a reference?
@@MilanJovanovicTech Because I read that the UI layer should not make a reference to the DAO layer.
what theme are you using in VS?
ReSharper dark theme
Milan, thank you for the video! I have a question about architecture. For example, I have 2 aggregate Roots (AR): "Company Customer" and "Individual Customer" which depended from abstract Customer class. So, as I understand I need to have 2 repository interfaces for each AR which will return appropriate ARs objects. But if I need to get all Customers, what should I do? In one hand I can use two requests (1 to get all Company Customers and 1 to get all Individual Customers) and combine them - it looks ugly. In other hand I can move repository interfaces to Infrastructure layer, create some common repository and CustomerDalDto - but here my application layer will be dependent from infrastructure layer... How to solve such task?
I found some definition of Repository in DDD by Edward Hieatt and Rob Mee that repository "mediates between the domain and data mapping layers using a collection like interface for accessing domain objects".
And here I understand some nice idea, that in Commands (CQRS) I defenetly need to save consistency boundary and some Domain rules. Cause of that I need to use repositories. But in Queries I don't need consistency boundary, I just need only data in some DTO variant. So, in my example I just need to use Query to get all Customers via dbContext in that Query.
Yes, Application layer will depends from Infrastructure. Is it a bad idea or some kind of compromise?)))
I suggest just moving the DbContext to the application layer, if you want to use it directly
@@MilanJovanovicTech Hi Milan, in the real project, which one do you prefer? place DBContext in the application layer or many common repositories for complex query?
Any advice?
One thing that slightly bothers me is that you abstracted the EFCore implementation away with a repository to then leak it back into your domain. In other words your db model is a straight copy of your domain entity so that tells me that you either add something funny in your domain entity to make it work with efcore(leak) or your models arent as complex yet and you will walk against that problem sooner or later.
I do neither of the two things, actually. I model my Domain using DDD principles. It's when it comes to configuring EF that I make adjustments to fit everything into a relational model.
@@MilanJovanovicTech right as in you modify your domain entity to fit the needs for efcore? Unless im not aware of something magical on efcores side
@@donnyroufs551 No, that's conforming to EF Core. You want to avoid that at all costs. Design the domain model regardless of the peristence mechanism you are using.
You can configure how you map the domain model to the database with EF Fluent configurations. Perhaps I should make a video about this?
@@MilanJovanovicTech but thats my point, I dont see how thats possible without walking against problems when straight up returning the db model from your repo?
@@donnyroufs551 Maybe we need an example?
Very useful 👍
Glad you think so!
Hi Milan! What design pattern do you know for SocketListener and Client (example, console apps and client server communications)?
It is very difficult for me to make a server (listener) with disacoupling, and link the socket to a logged user.
Where can I find information about this?
How can I think a P2P solution for example or any solution in this concept?
What does this have to do with the Repository pattern? 😅
@@MilanJovanovicTech I don't know any other way to contact you. You are talking about repository pattern and as you don't have any video of TcpListener and the best practices. So, I decided to write my question here. =)
Hello good afternoon, I loved your video, thanks for sharing knowledge. I wanted to ask you if it is possible for you to make a video by applying it to windows forms. I can't figure out how to apply it. From already thank you very much. Greetings from Argentina
I can't promise I'll deliver on this, since I'm mainly focused on Web applications
@@MilanJovanovicTech Simply thank you for your time in responding. Greetings.
Maybe it's just me working with crappy DB , but SingleOrDefault > FirstOrDefault when getting by ID.
In theory it shouldn't, since it tries to return 2 records from the DB
I have a question: Why don't you define the methods 'Add' and 'Remove' in the repository asynchronous just like the query methods? Thank you very much.
Because their changes are done in memory (EF ChangeTracker), there's nothing going to the DB so no need for async
Hi, Milan. Thank you for yet another awesome video! I have learnt a lot from all of your videos! I saw you always use dbContext.Set() method instead of dbContext.Entity, there are a difference between them I don't know or they are doing the same thing?
I usually don't create DbSet properties, so I get my DbSet through the Set method
@@MilanJovanovicTech thank you!
Hello MilanJovanovic Tetch
I really like your content, could you make a video on how to use C# entity framework 4 for a good project architecture, using msql or sql server?
EF 4? I sincerely doubt that
Hello, Milan :)
I like all your videos! Congratulations for making understanding complex subjects in general really simple to be put to practice, mostly.
Do you have some content in which you explain the Unit of Work Pattern and how you would implement it by using EFCore and the IUnitOfWork interface? Any pointers? I would very much like to hear it from you!
Best regards and keep rockin'!
I keep getting that question recently, so I surely will make a video about it!
Yes please show how you do the EF changes (add,delete,update) using your Unit of Work.
It would also be good if you show how to use EF without using API. That is say a Windows Services App using EF that gets a IEnumerable. Then make changes to the DTOObj, and then apply this change back to EF without errors of it's being track, .... Plenty on doing this but all use APIs. Nothing on using EF without API updates.
Am Pretty New to Patterns. Why is the ICommand different in this video and CQRS Dosent Have to be complicated? Could you shed more light as what I see is both seem to be CQRS Pattern
Could be part of a different series, but it comes down to the same concept
Maybe there is better video to ask about that but whatever 😊
Why usually implementation of unit of work is not tightly coupled to repositories, I mean that (for now let’s forget about mediator pattern) would it be more practical to access repo from uow?
//just a sample
using(uow = unitOfWorkFactoryX.Create()){
uow.SomeRepository.Save(…)
or
uow.Repository.Save
}
Especially when there is more than one context, asking hypothetically 😅
I personally dislike that approach, as it's not clear which dependencies my class has. With explicit repositories it's easier for testing.
Odličan video
Hvala puno! 😁
Hi, Do i have to register every repository in Program file before i can use it?
Yes
Milan I think Repository shouldn't be in the Domain of clean Architecture, is this normal in DDD?
@bot oh ok my bad, I didn't see that was Interface Thanks
I tend to place them in the Domain layer, because I only use them for interacting with my domain model (and not for querying)
why should we define Repository Interfaces in domain layer instead of application layer ?!
Discussed here: ua-cam.com/video/rG090b5MRGo/v-deo.html
Great content
Thanks
repository pattern falls apart when you need a bunch of different combinations of includes for different purposes
True, but there are ways to solve that also with Specification Pattern
Still, I can argue there is no point in using the repository pattern when you have EF. (unnecessary code and complications)
What's your argument?
@@MilanJovanovicTech Same old one xD with a newer solution. IMO there are 2 benefits of using the repository pattern along with EF core, easier testability, and query encapsulation.
as you correctly said EF context is a combination of repository and unit of work so if we can solve the two problems that I mentioned we don't need a repository pattern.
test -> it is completely possible and easy (with a small test framework) to mock and test the DbSets directly.
encapsulation -> usually and most of the time it is not necessary to encapsulate queries that usually we only use once but for those queries that we need to encapsulate and reuse we can achieve the same results using a simple static class and some extensions.
I think there is a tradeoff between clean coding and complexity when we talk about repository pattern and EF, I personally believe the repository complexity and an extra layer don't help at all.
Although, In my experience, it is really clean to have repositories in small projects or microservice projects but having a big code base like a monolithic project … repositories are a real pain and sometimes really messy.
Brabo, muito bom (y)
Thanks!
What's your story pink glove?
I think name "IsEmailUnique" is a little bit misleading.
How so?
@@MilanJovanovicTech unique if there is no duplicates. What you're really checking is: does email already exists within database/repository.
This is not a very good solution because as you eagerly include more and more navigation properties, the code will become unmanageable.
There are ways to solve this without the code becoming unmanageable. Using the Specification pattern, is one example.
@@MilanJovanovicTech I will check it out . Thanks!
Repository is just an unneeded layer of abstraction IMO.
Why?
SO THE REPOSITORY PATTERN IS GOOD NOW??? 😊 BTW, YOU'RE STILL USING REPOSITORY/UOW WRONG.
What's the right way to use them?
What's your story pink glove?