How I Use The Generic Repository Pattern In Clean Architecture

Поделиться
HTML-код
  • Опубликовано: 22 авг 2024

Комментарии • 196

  • @MilanJovanovicTech
    @MilanJovanovicTech  Год назад +5

    Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
    Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt

    • @lahao1
      @lahao1 11 месяцев назад

      sir, you just got my voice ! 🫡

  • @dansmif
    @dansmif Год назад +32

    Adding a repository layer on top of EF is just wrapping one repository pattern with another. The DbSets in your context are already your repositories, and the DbContext itself implements the unit of work pattern.
    It's worth bearing in mind that patterns are often derived from other languages (especially Java) that lack nice things like extension methods in C# so there's sometimes better ways to approach things. For example you can extend the DbSet collections in your EF context with extension methods to add methods like GetProductById to DbSet. You can even add generic GetById methods to all your DbSets using a single extension method. It's much cleaner this way, with less code and less complexity.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +10

      I'm focusing on my Domain design, and dictating what the Application layer can do with those repositories. You're missing the point, because "EF is a repository already" doesn't matter. You can use just EF, and you'll be fine. But that has other implications for your application.

    • @user-em8rt4eq2s
      @user-em8rt4eq2s Год назад +1

      i had thousand problems with tis method, dont use in large scale projects

    • @123sampletext5
      @123sampletext5 11 месяцев назад +1

      This is a very unintuitive solution. No one expects to use the logic coded only in extension methods + by adding extension methods to DbSet which is a strictly EfCore class you tie your project to use EntityFramework only and you are not able to switch it to different project/database connector.

    • @PauloWirth
      @PauloWirth 11 месяцев назад +4

      Seriously, this is like repeating the same argument over and over.
      Specific repository or generic are not silver bullets.
      Also, there will be projects you will come across multiple database providers, and the generic repository might be useful.
      Also, combining it with the specification pattern helps reduce the number of overloads for read commands.

    • @Ryan-mg2uv
      @Ryan-mg2uv 7 месяцев назад

      How would this work if you wanted to mock out the db for testing and use in memory data instead of data in a db? In this case that you mention, you are stuck with using EF and a db

  • @frankhalbach2591
    @frankhalbach2591 Год назад +16

    Nice video, i’d love to see a version of this with Dapper instead of efCore.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Dapper one would be much more verbose on the implementation side - and we don't have a UoW 😁

    • @frankhalbach2591
      @frankhalbach2591 Год назад

      Right, i use dapper in my project and have some repetition with the scenarios you solve in the video.

    • @Greenthum6
      @Greenthum6 Год назад +1

      Dapper benefits from repository pattern much more than EF

    • @xustis
      @xustis 7 месяцев назад

      i love that too, i am using dapper and i dont know how call the base repository method from my service, calling the specific repository interface with DI :S

  • @hkoueke
    @hkoueke 2 месяца назад +1

    Hey there. Long time sub from Cameroon. Keep up with videos, i learn a lot from them.

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 месяца назад

      Thanks a lot, glad you're getting value from the videos :)

  • @victorgarcia3526
    @victorgarcia3526 Год назад +1

    This is an approach I used in a project where you had to connect to multiple providers via API and keep their information in our db, this helped a lot to reduce the code generated via the integration of every provider, and we could have a lot of providers almost seamlessly

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      That's awesome. Which providers were you working with?

    • @victorgarcia3526
      @victorgarcia3526 Год назад

      @@MilanJovanovicTech it was a tourism related company so they were APIs like booking, Expedia... We used that pattern to keep all the different information for all these providers in different tables

  • @danilonotsys
    @danilonotsys 10 месяцев назад +2

    I like to use generic repositories these days, since many database providers - relational or not - support queryable linq and it's relatively easy to implement an in-memory cache or change tracking system for any of them that don't support EFCore. When I need a custom operation on the repository, lets say it due to a need of a very optimized query or bulk update or insert, then I create a specific method in the domain repository interface. This has worked very well for many projects I've worked on.

  • @jonclark25
    @jonclark25 9 месяцев назад +1

    When using generic repository pattern with EF I always liked to make the methods simple and return an Iqueryable so the inheriting class can modify the "Base query" and add to it. E. G the repository class has a getById but the inheriting class can call this, get the Iqueryable and add a where clause to it to filter further more but only actually executing once.

  • @alessandrohudson5221
    @alessandrohudson5221 Год назад +2

    Valious tips Milan!! Depending of project, can be useful

  • @xenofenus
    @xenofenus Год назад +1

    Patreon email coming in clutch to quickly absorb Milan's new content

  • @sadkcoban625
    @sadkcoban625 7 месяцев назад +1

    Thank you for your answers. I will approach things like this in my future applications I don't know is it true or not. I will use repository pattern in basic crud operations becauase it is good especially when you want implement something like soft delete mechanism. But in complex queries no matter I use cqrs or not I will do in bussiness/application layer because it really gives complexity. I really see a lot solution people does not use select query and directly map into objects. What is the reason to get all the data from database and map to them. Because if you get 8 columns of data maybe you need 4 columns of it..Map after get all the data. Select after ToListAsync.All columns queired allready!. This is performance issue.If it is wrong to use dtos in repositories object or dynmaic i should do this operation in bussiness layer. So I should abstract away dbcontext because my application shouldn't reference persistence layer.I am really tired to search how to solve this. Thanks for the answer again.

  • @i.paradox
    @i.paradox Год назад +2

    Thanks for sharing your valuable knowledge.

  • @marcnacionales7786
    @marcnacionales7786 Год назад +2

    I'm learning a lot on your videos. 😁
    I'm just wondering if, is it better to have a method GetAsync with a parameter of an expression (Expression predicate = null) rather than adding a method GetByIdAsync ?

  • @svorskemattias
    @svorskemattias 11 месяцев назад +1

    The order and orderlines could be defined using the ownsmany-relationship, and efcore will handle the include for you, so you can skip the override.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Do you always want to include them, though?

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      @@MilanJovanovicTech when reading for modifying, yes! I've used another set of dbcontexts with plain hasmany-relations for readmodels. Not sure if it's a good idea in the long run, but it has been ok so far.

  • @user-bx2er2zx5u
    @user-bx2er2zx5u Год назад +3

    But you don't solve the problem with interface that your repository don't need - CustomerRepository needs only generic Add , but get also Remove and Update .

    • @TheFeljoy
      @TheFeljoy Год назад

      Not quite. Because the interface isn’t exposing the methods, they cannot be accessed outside of the Infrastructure layer. The domain & application layer will only use the interfaced methods :)

    • @Forshen
      @Forshen Год назад +1

      You can argue that you most likely always need CRUD actions on an entity. But I do get our point. There are definitely scenarios where you don't need the full CRUD actions.

    • @user-bx2er2zx5u
      @user-bx2er2zx5u Год назад

      @@TheFeljoy I mentioned only interface methods . Dont get your point.

    • @user-bx2er2zx5u
      @user-bx2er2zx5u Год назад

      @@Forshen So Milan said that he does not like it because all repo's get access to full crud , but we can dont need it . And than make same stuff.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +2

      I'm not worried about having these methods in the implementation, since they aren't exposed to the consumer

  • @mocca9016
    @mocca9016 6 месяцев назад +1

    Really good and concise video explaining the pattern. I have one question that I couldn't find an answer on. What if we are working with a DbContextFactory? How would the Repository and UnitOfWork class use the context in this case?

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад +1

      Configure them to resolve the DbContext form the factory? 🤔

    • @mocca9016
      @mocca9016 6 месяцев назад

      @@MilanJovanovicTech So we wouldn't inject the repository with DI but instantiate it in the calling method with a created context? Or is there another way to make the repository use the created context, preferably with DI? Sry for the stupid question 😅 Because what I think the problem is, when having DbContextFactory in repository class, it always creates a new context for each repository method, but I would like the repository and the unit of work to use the same context. Maybe I'm just missing something

  • @Tof__
    @Tof__ 11 месяцев назад +2

    What exactly are the OrderId, ProductId classes?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Strongly Typed IDs: ruclips.net/video/LdrMdIabE1o/видео.html

  • @yiliang9702
    @yiliang9702 11 месяцев назад +1

    Great video. if the app logic is complex. we better make a abstract class between actual service class and their interfaces. it is more flexible.

  • @kp_xcess
    @kp_xcess 6 месяцев назад

    It is interesting that you decided to define the repository interfaces within the domain project. I myself usually define them within the application layer, because it is actually the application that determines what exact data it needs, based on what the application actually does. The domain layer should not be bothered with that. Of course it does still own its own entities, value objects and contains all related domain logic.
    One down side of my way however is that a lot of these repository interfaces end up in the Common area, since their usage often spans across multiple application microservices... And then also your reasoning does make sense and got me thinking about it once again.
    I've yet to decide if we will be switching back to defining 'em in the domain layer after all :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад

      Maybe we can look at it as "domain repositories" and "application repositories"? The naming might be a bit strange, but I think it describe what you/me are doing

    • @kp_xcess
      @kp_xcess 6 месяцев назад

      @@MilanJovanovicTech Well that does indicate the difference.

    • @manueliriarte1535
      @manueliriarte1535 6 месяцев назад

      thought the same thing. interesting approach but I would not put them in the Domain, good to hear I wasn't the only one thinking of that.

  • @Flanno91
    @Flanno91 Год назад +1

    Great video Milan. Would love to see how something like this would work with the MongoDB driver. First thought is that each collection is it's own property in the MongoDB context and can't just use the generic Set property. As far as I'm aware?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Will check to see how this works with MongoDb. Could possibly require some re-design. 🤔

  • @KristofGalNix
    @KristofGalNix 11 месяцев назад +1

    Awesome, love your explanation. Earned a subscriber. 💪

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Thanks a lot! Hope you found the other videos just as valuable 😊

  • @feli4521
    @feli4521 Год назад +1

    I really like this approach when using ef core with the repository pattern

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Did you use it before?

    • @feli4521
      @feli4521 Год назад

      @@MilanJovanovicTech Yes, it avoids having to write repeated code in the repositories and it allows you only to write specific queries only for certain entities

  • @MrNickP
    @MrNickP Год назад +2

    I'm primarily a DB developer so forgive my ignorance but does entity retrieve full objects from the DB even if you only use a few columns?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Yes, that's one of the drawback of ORMs. If you want to load an entity, it'll have all the columns. You could optimize it by manually fetching specific columns, but most of the times you wouldn't do this if your intent is to write back to the DB. If you are using an ORM for a query (read) than you will definitely only want to fetch the columns you need.

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      This is not an ORM drawback! In ef core you can do it how you like it! Either you project your entities onto a dto, and EF CORE will only select the columns needed. This is good for readonly operations! In this case however, when trying to do DDD, you want your aggregates to be fully loaded into memory, because the aggregates define your consistency boundary. The aggregate can now use all the information in the aggregate to validate the operations your doing on it! If this means pulling too many unwanted columns from the database, maybe your aggregate is to big? Maybe it holds many unrelated fields, that don't have to be inside the same consistency boundary?

  • @kodindoyannick5328
    @kodindoyannick5328 6 месяцев назад

    Great video! Thank Milan.

  • @ARESCOM_PA
    @ARESCOM_PA 9 месяцев назад +1

    Thanks for this helpful video Milan! Wouldn't it be great to use this generic repository pattern with CQRS and only the Command uses it and the Query part still uses EF directly? Should be a good content for another video?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 месяцев назад +1

      It's something I've done in future videos, more or less

  • @jonny.rubber
    @jonny.rubber Год назад +3

    Isn't Moq caught secretly gathering email addresses?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Yes, in some versions. The versions before that (and after) are fine

    • @hrobertson4
      @hrobertson4 10 месяцев назад

      It also wasn't really secret, they weren't caught, they announced it

  • @pete9049
    @pete9049 Год назад +1

    holy this is clean af

  • @salmanshafiq8151
    @salmanshafiq8151 Год назад +1

    Nice video, Milan.
    But here, inspite of need an add method for an entity, the entity has now four or more method by inheriting the generic repository.
    1. Then What is purpose of using interface?
    2. Why the repository expose the methods that doesn't need?

    •  Год назад

      Remember that you always use the repo interfaces defined at the domain layer. You don't have access to the members of the implementation so you won't see the generic repo methods.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      1 - I explained that in the video, in-depth with my reasoning
      2 - The repository implementation is internal - you're working with the interface

  • @pagorbunov
    @pagorbunov Год назад +1

    You said that the domain layer dictates how the repository interfaces should be implemented but isn't it vice versa? it looks like knowing that the reads and writes are separated and ef is an orm forces you to create such interfaces where the reads are async methods and writes are not.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Repository doesn't do writes, just adds stuff to the repo. UoW takes care of write. I don't think async (Task) in domain is bad, anyhow.
      The repository dictates the usage (not the implementation).

  • @olamidejames7968
    @olamidejames7968 11 месяцев назад +1

    HI @MilanJovanovicTech, I really enjoy watching your tutorials. Please do you have any video on unit testing ef core async methods like AnyAsync, FirstOrDefaultAsync, e.t.c as well as AsNoTracking method?
    Thanks

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Maybe this: ruclips.net/video/tj5ZCtvgXKY/видео.html

  • @ardavaztterterian1211
    @ardavaztterterian1211 9 месяцев назад +1

    What are the domain events for in the Persistence layer? Shouldn't they be raised from the Domain/Application layer?

  • @ibrahimoguzhanyilmaz3451
    @ibrahimoguzhanyilmaz3451 Год назад +2

    why would you implement UnitOfWork just to call SaveChanges?

    • @ibrahimoguzhanyilmaz3451
      @ibrahimoguzhanyilmaz3451 Год назад

      I asked this to GPT and this is the answer. But it is still not a good answer for me.
      When using the Entity Framework (EF) in .NET, the DbContext class already provides a SaveChanges() method, which might make it seem redundant to wrap this with a UnitOfWork. However, implementing the UnitOfWork pattern can still be beneficial, even if all you're doing is calling SaveChanges(). Here's why:
      Abstraction: UnitOfWork abstracts the underlying data access logic from the rest of the application. By doing so, it makes your application less dependent on a particular ORM or database technology. If you ever need to change your data access logic or even switch to another ORM, you'll have a single point of change.
      Testability: With the UnitOfWork pattern, you can mock your unit of work in unit tests. This makes testing easier, especially if you want to test services that have database interactions without actually hitting the database.
      Multiple Data Sources: In more complex applications, you might be dealing with multiple databases or data sources. A UnitOfWork can help manage transactions across these different sources.
      Decoupling: It allows services to be decoupled from the specific persistence mechanism being used, making the architecture cleaner and more maintainable.
      Flexibility: In the future, if you need to add more functionality around the commit (like logging, event raising, etc.), you can do it in the UnitOfWork without altering your service or repository classes.
      Transaction Management: The pattern can simplify transaction management, especially if there's a need to handle custom business transactions that span multiple operations or repositories.
      Clarity: By using the UnitOfWork pattern, you're signaling to other developers that you're aggregating operations for eventual transactional persistence. This can help in understanding the application's flow and logic.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Would you make each repository method also go to the DB?

    • @Greenthum6
      @Greenthum6 Год назад

      ​@MilanJovanovicTech Isn't that the main responsibility of a repository? Your get methods already access the DB. Excluding SaveChanges from the repository and renaming it to UnitOfWork outsources transaction handling to application logic.

    • @ibrahimoguzhanyilmaz3451
      @ibrahimoguzhanyilmaz3451 Год назад

      @@MilanJovanovicTech i feel you, i've never thought uow like that, thanks you :) love your content :)

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      ​@@Greenthum6I guess because you don't really know how many repositories you wanna touch before committing the transaction.Even though most often you'd only want a single aggregate to participate in your transaction.

  • @matthewrossee
    @matthewrossee 11 месяцев назад +1

    Hi Milan! How do you deal with models in domain driven design that don't have behavior? In my project great majority of domain models have rich business logic (like 95%), but sometimes I encounter something that should just be a dumb data container, and it doesn't make sense to make it an aggregate root. For example when I create some Order aggregate, the client needs to pass some OrderOptions, like product's color, product's material, etc.. These cannot be a value object, because these order options have concrete price assigned to them, and should be seeded into the database (probably not gonna change often). So the only option I see is that the order option is an aggregate root, and then in Order.Create() factory method I can pass List. The thing I don't like about this approach is that OrderOption doesn't really have any behavior, other than maybe changing a price, that could raise some domain event. But still it doesn't seem like a good fit for an aggregate. Do you think that I should create some directory in domain layer for something like DataModels and throw anemic models there? I'm really curious how you'd handle this.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Just because it's anemic doesn't mean it's wrong. Some parts of the Domain simply won't have any behavior. Take a look at this for static data: ruclips.net/video/v6cYTcEfZ8A/видео.html

  • @SalmanTariq223
    @SalmanTariq223 Год назад +1

    You make the generic repository class in which all methods depend on the type of class.
    While I think there should be generic methods which are independent and called for any entity type.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      And how would you do that?

    • @SalmanTariq223
      @SalmanTariq223 Год назад

      @@MilanJovanovicTech don't make custom repositories like OrdersRepository or SalesRepository etc. Just make a generic Repository by using specification design pattern.

  • @sadkcoban625
    @sadkcoban625 7 месяцев назад +1

    Hello if I want to implement select can I use dto in repository is it good practice what is your suggestion? Some people says repository should return domaim entities repository should not use dtos

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 месяцев назад +1

      I'm on the same side of the fence: repositories should only work with domain entities

  • @dionismendanha4649
    @dionismendanha4649 11 месяцев назад +1

    I'm looking forward to seeing a video explaining about upgrading with multilevel. Is there a way to do this dynamically?

  • @ravindranaths513
    @ravindranaths513 7 месяцев назад +1

    What if any repository class doen't want the functionality (method), which is defined in base repository class?

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 месяцев назад

      Well, nothing really. You can't remove it from the base class.

    • @ravindranaths513
      @ravindranaths513 7 месяцев назад

      1) can we write : throw NotImlementedException in child repository classes, to suppress not required methds of base Generic repo class?
      2) If not then, this Generic repository approach is not usefull where only writing method (POST) is there. Forex: in case of some business transations, having only adding new records into db table is enough.
      Plz give your comments

    • @kp_xcess
      @kp_xcess 6 месяцев назад

      @@ravindranaths513 Throwing NotImplementedExceptions is only for methods that are yet to be implemented (and _will_ be implemented). They should never be thrown purposely otherwise. In this case you'll simply get the methods for free within other repositories too, even if you don't (currently) need them 😉

  • @patrykwikacz869
    @patrykwikacz869 Год назад +1

    Very nice and usefull video.
    What theme are you using for visual studio?

  • @hassenlazli6047
    @hassenlazli6047 3 месяца назад

    Hi, what should we do when we find ourselves with a service like UserService that injects, for example, 10 repositories? How can we make it cleaner?

  • @krcarbo
    @krcarbo 11 месяцев назад +1

    Thanks for the video and the explanations. Is it possible to have access to the code please?

  • @Cornet435
    @Cornet435 Год назад +1

    What do u think about second optional parameter in GetByIdAsnc where you have array of expresionss. If this array is not null we just applay all includes expresionss.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      I'd be careful with expanding the interface like that, but it should be fine

  • @tasin5541
    @tasin5541 11 месяцев назад +1

    How would you handle tables that don't have Id? Or use composite keys?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      Will they need repositories at all?
      Composite keys are a bit complex, so probably a slightly different solution

  • @jadenrogers3133
    @jadenrogers3133 Год назад +1

    Great video, EF is a repository 😂 I think they missed the point. Would love to see a video on GUID vs X for id's that one also gets a lot of debate. I notice you use GUIDs, do you do this on large systems?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      There are sequential GUIDs and ULIDs without the drawbacks. But GUIDs are mostly fine (albeit random). And in a distributed system you have to use something like that.

  • @jorgellanque7704
    @jorgellanque7704 9 месяцев назад +1

    Where is the link of the code repo?

  • @Benke01
    @Benke01 8 месяцев назад

    Regarding the Include: personally I think this is a requirement only the consumer of the repository knows about. And I think the repository shouldn't specify it because its related to the domain logic. One consumer of a repository method might need 2 types of .Include() while another might need 3 others or another .ThenInclude(). You then have two choices: either let all consumers of a method fetch the total set of Include() flavours or you let the consumer specify the include as a functional parameter to the repository method.

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 месяцев назад

      So either go for everything - or use something like a specification pattern

    • @Benke01
      @Benke01 8 месяцев назад

      @@MilanJovanovicTech You could use the specification pattern but that doesn't necessarily address the issue. Depends on the implementation.🙂
      In a real world example a repository method can and should be able to be used by multiple consumers. But rarely they have the exact same needs when it comes to includes.

    • @kp_xcess
      @kp_xcess 6 месяцев назад

      @@Benke01 Then just let the repository offer multiple variants of the method, either by adding an additional parameter or just create a few extra methods that include specific things.

    • @Benke01
      @Benke01 6 месяцев назад

      @@kp_xcess That would quickly escalate to multitudes of methods. And their naming... 😥

  • @smeta72
    @smeta72 Год назад +1

    Thanks!

  • @rouziuzi
    @rouziuzi 6 месяцев назад

    Very useful. Hvala :D

  • @sergeu90
    @sergeu90 4 месяца назад

    I see in your examples unit of work in command. But if need call multiply commands and after that call unit of work. It is need to do in controller if we speak about mediator ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  4 месяца назад

      I strive to send one command per request

    • @sergeu90
      @sergeu90 4 месяца назад

      @@MilanJovanovicTech But then if i want to create specific command need to create a lot of diff commands. But better in conroller call multiply small comands and after that call commit

  • @sunguhan
    @sunguhan 7 месяцев назад

    First of all, great video! I really enjoy your work so keep it up!
    I am currently working on a clean architecture solution and I'm are quite new in the concept and noticed that you refer the domain layer in infrastructure.
    Is it alright that infrastructure can reference to classes in the domain layer or is it only application who have access to this layer? I mean based on the clean architecture diagram, the domain layer is the inner most layer where the application layer is the adjacent layer to domain while presentation and infrastructure are the outer layers.
    So im just a bit confused on how outer layers can reference each inner layers without breaking best practices? 😅

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 месяцев назад +1

      Yes, the outer layers can reference the inner layers.

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 месяцев назад +1

      - www.milanjovanovic.tech/blog/clean-architecture-and-the-benefits-of-structured-software-design
      - www.milanjovanovic.tech/blog/why-clean-architecture-is-great-for-complex-projects

  • @techpc5453
    @techpc5453 11 месяцев назад +1

  • @svorskemattias
    @svorskemattias 11 месяцев назад +1

    What happens when mediator fails to handle your events? They just dissappear, and the initial transaction (your savechanges) is completed! This is not good is it? The change you made in the domain is probably not idempotent, so you can't just run it again and hope the events succeed next time. Shouldn't you save the events along with the entity in a transactional outbox!?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      I explained in the Domaim events video this specific problem, and how to solve it

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      @@MilanJovanovicTech I'll take a look!

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      @@MilanJovanovicTech This? ruclips.net/video/BimfDeDV4yU/видео.html
      Because it only briefly touches the transactional outbox at the end. It seems like you have solution for this without transactional outbox hidden somewhere, but I can't find it, nor understand how it would work. :)

    • @svorskemattias
      @svorskemattias 11 месяцев назад

      Oh. This one? It is just as problematic as it was before introducing events, only now the chain of events can be basically infinite and crash anytime? Transactional outbox is the only way, as I see it. ruclips.net/video/AHzWJ_SMqLo/видео.html

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      @@svorskemattias This one ruclips.net/video/XALvnX7MPeo/видео.html 😅😅

  • @anilkarasahh
    @anilkarasahh Год назад +1

    How would this behave if an entity had a composite key?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Now you're reaching... I think it's still doable, but the GetById method would need to be updated slightly on the key filtering part

  • @arivoarivo
    @arivoarivo 8 месяцев назад

    @MilanJovanovicTech
    I thought we should only create repositories for aggregate roots in DDD pattern?
    And 2nd question, if I want to implement a custom query for an entity which is not an aggregate root, where should I put that

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 месяцев назад +2

      That rule is too constrictive for most applications

  • @attilaguba856
    @attilaguba856 Год назад +2

    Nice one ! Could you make the same Generics Repository pattern /UnitOfWork/ with Stored Procedure and EF! That would be amazing! Thanks

    • @Code_Bits
      @Code_Bits Год назад

      Honestly, you should try avoid using Stored Procedures if possible.

    • @attilaguba856
      @attilaguba856 Год назад

      @@Code_Bits can you explain why ? I have UnitOfWork with Generic Repository and I thought with Stored Procedure you can avoid sql injection?!? So what do you suggest?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      How will you run into SQL injection with EF?

    • @attilaguba856
      @attilaguba856 Год назад

      @@MilanJovanovicTech so what do you suggest? Leave just EF in my project without Stored Procedure? It's better ?

    • @Code_Bits
      @Code_Bits Год назад

      @@attilaguba856 I think the first Google search would answer your question honestly.

  • @jwbonnett
    @jwbonnett Год назад +1

    Why use UOW pattern when you can just use the DB Set as it already does what the UOW does?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Sigh... Didn't I explain it in the video?

    • @jwbonnett
      @jwbonnett Год назад +1

      @@MilanJovanovicTech No, I'm talking context. You explain why you use it. I am asking why not use it in a specific way, as all you're doing is recreating functionality that is already available.

  • @programmingskills3404
    @programmingskills3404 Год назад +1

    Nice video

  • @sadkcoban625
    @sadkcoban625 8 месяцев назад

    Hello. How should I implememt select with this pattern. I implemented one but it is complex. Should i implement another overload for select functionality thanks for answer.

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 месяцев назад +1

      Might be better off creating a concrete method for complex queries

  • @MDM666666
    @MDM666666 Год назад +1

    Which keyboard are you using?

  • @aah134-K
    @aah134-K 11 месяцев назад +1

    How did you wire the unit of work class

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад +1

      As a scoped service -> services.AddScoped()

    • @aah134-K
      @aah134-K 11 месяцев назад

      @@MilanJovanovicTech i mean doest have to be the same dbcontext, used in the repository class or two scoped instances are ok, one to do the databas access one will do the save changes.
      What I had before a method within the abstract reposotory class, this method will do save changes.

  • @michaelgrass
    @michaelgrass 4 месяца назад

    Why do we use SingleOrDefault() instead of Find()?

    • @MilanJovanovicTech
      @MilanJovanovicTech  4 месяца назад

      Same result, but I don't like using Find. Prefer writing my LINQ condition

  • @microtech2448
    @microtech2448 9 месяцев назад

    Should Domain project be allowed to reference in Persistence project? As per clean architecture diagram, domain should be referenced in Application project only?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 месяцев назад

      No - it's the other way around. Persistence can reference Application/Domain

    • @microtech2448
      @microtech2448 9 месяцев назад

      @@MilanJovanovicTech ok, but if one may want to keep both layers independent of each other then in which project domain and DB entities should be mapped to each other and what would be appropriate way of mapping them?

  • @krccmsitp2884
    @krccmsitp2884 11 месяцев назад +1

    CRUD repositorys: 👎🏼 / Domain repositorys: 👍🏼

  • @rishiraj1616
    @rishiraj1616 4 месяца назад

    hmm so if I am not using EF then how to have a generic repository pattern?

  • @piottrk
    @piottrk 3 месяца назад

    Hi, is it possible to review your project somewhere (maybe git?)?

  • @RespectNaturalBeauty
    @RespectNaturalBeauty Год назад +1

    Could you please project regarding this?

  • @lettuceturnipthebeets790
    @lettuceturnipthebeets790 Год назад +1

    awesome! it's quite similar to the approach we've used at my previous work. what do you think of accessing generic repository via a factory or builder of some sort? would it be bad to expose generic repo building based on specified entity type, even if the entity doesn't have an concrete repo?

    • @Code_Bits
      @Code_Bits Год назад +1

      You can directly use Entities without an concrete repository for them. So you'll only be able to use the Add(), Update() etc... methods for that specific entity. If you implement the repositories the way Milan implemented them you could also make these methods virtual and override them in your specific repositories if needed. At work we also used this implementation of the generic repository pattern and it's a very good way imho. We also used a IUnitOfWorkFactory to create the Unit of Work and retrieving from the dependency injection container the repositories we needed.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      How that builder work? Got an example?

    • @lettuceturnipthebeets790
      @lettuceturnipthebeets790 Год назад

      ​@@MilanJovanovicTechI think there were some ideas with exposing Set() DbContext method (where TEntity is IEntity, of course) and some scoped caching of the built repositories in a concurrent collection (if the repo is needed again in the same request)

    • @lettuceturnipthebeets790
      @lettuceturnipthebeets790 Год назад

      I personally root against it, since there could be more Entities than DbSets, which could lead to some runtime exceptions

    • @Code_Bits
      @Code_Bits Год назад

      @@MilanJovanovicTech I don't have an example unfortunately, however the Factory created an UnitOfWork instance with the right DbContext. This UnitOfWork instance was used to get repositories (like the Product repository) which only accepted domain entities and automatically mapped them to the DbEntity (in case of an Add()). In case of an any other operation like Update() etc we also passed in a domain entity which would update the DbEntity. The repository took care of mapping them and you only needed to have the mapping configured and the repositories registered in your DI container. This worked very well in our case since as you can guess you only needed to inject the factory within your classes and not the UnitOfWork and repositories.

  • @andtkach
    @andtkach 11 месяцев назад +1

    Great

  • @charlesschneiderp
    @charlesschneiderp Год назад +1

    Is this project code available on git? Thanks!

  • @iamorhanmir
    @iamorhanmir Год назад +1

    First Viewer ❤

  • @jessegador
    @jessegador Год назад +4

    You are just reinventing the wheel. EF is already a repository.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      What about code duplication?

    • @svorskemattias
      @svorskemattias 11 месяцев назад +1

      @@MilanJovanovicTech Its nice to put an interface around things for many reasons! The repository is not reinvented by doing this. Its just getting a nicer packaging, communicating through specific interfaces what operations are allowed. Also, you gain mockability.

  • @microtech2448
    @microtech2448 Год назад +1

    Nice video