Mapping Domain-Driven Design Concepts To The Database With EF Core

แชร์
ฝัง
  • เผยแพร่เมื่อ 20 ก.ย. 2024

ความคิดเห็น • 203

  • @MilanJovanovicTech
    @MilanJovanovicTech  ปีที่แล้ว +7

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

    • @sergbo3114
      @sergbo3114 3 หลายเดือนก่อน

      What about Aggregate root mapping in this case?

  • @davearkley7014
    @davearkley7014 ปีที่แล้ว +17

    Another great video, really useful. A few thoughts though....
    Your property on Customer is called Email, but it's an EmailAddress. Small bugbear since I have a customer who store entire Emails in their database, and since they don't archive it's TB of data. Also according to RFC 5321, which defines the Simple Mail Transfer Protocol (SMTP), the maximum length of an email address is 320 characters. This includes both the local part and the domain part, as well as the '@' symbol that separates them. However, RFC 5321 also recommends that email addresses should be no longer than 64 characters for the local part and 255 characters for the domain part, as these are the limits imposed by the most commonly used email systems. Therefore, while the maximum length of an email address according to the RFC is 320 characters, it is generally advisable to limit email addresses to 64 characters for the local part and 255 characters for the domain part.

  • @anilkarasahh
    @anilkarasahh ปีที่แล้ว +4

    I have always wondered how the EF Core maps value objects to the databases, never had time to look up, though. Everything I learn about EF always feel magical. Such a great companion! Thank you for this nice video, Milan!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +3

      Just additional columns in this case, and for OwnsMany it's a separate table

    • @MarcusKaseder
      @MarcusKaseder ปีที่แล้ว +1

      You can also specify how to map owned properties. For example, price can be mapped to a separate table. But it makes no sense for most cases.

    • @pilotboba
      @pilotboba ปีที่แล้ว +1

      @@MarcusKaseder Yep, you can also map it as JSON.

  • @timurrozhok2685
    @timurrozhok2685 10 หลายเดือนก่อน +4

    I find this tutorial very comprehensive, since the narration escalates from simple examples to most complicated ones. Alternative approaches are also pointed out. And yet it's very easy to watch. 'Q' stands for "Quality", and 'A' stands for "Awesome"! :)
    By the way, I guess some read-only wrapper collection is knocking in the door in case of that 'LineItems' property. Perhaps even with a lazy initialization of the wrapper. But that's just details :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      Glad you liked the video :)
      A readonly wrapper is an interesting twist. 😁

    • @timurrozhok2685
      @timurrozhok2685 10 หลายเดือนก่อน

      @@MilanJovanovicTech Yeah, my notion was quite obvious 😄 But anyway, I meant not to create a new list on each getter call.

  • @gianlucalocri
    @gianlucalocri ปีที่แล้ว +3

    Your videos are pure shining gold!
    Thank you Milan!

  • @okcharles7
    @okcharles7 7 หลายเดือนก่อน

    Wow. I can't understand why the algorithm has attracted me to this video just now, which was the subject I were heavily searching.
    I have been using configurations just as a supportive role to mapping conventions on entity classes, which means I have always been defining entity classes and domain classes separately.
    Your video shows how to effectively use them with less maintenance points.
    Thanks for great work.

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +1

      Maybe because you were heavily researching 😁 In any case, glad the video was helpful

  • @MehediHasan-xd6rj
    @MehediHasan-xd6rj 4 หลายเดือนก่อน

    Whenever I am learning new things in C#, I always try to verify how Milan does it. Thank you for these nice videos.

  • @ahmedmostafa-zu5kr
    @ahmedmostafa-zu5kr ปีที่แล้ว +1

    actually, It's my first time posting a comment under a youtube video. But I really enjoyed your way of simplifying topics

  • @joga_bonito_aro
    @joga_bonito_aro ปีที่แล้ว +3

    Great video as always. One thing I would add is a base class/record for StronglyTypedIds. It would make your life easier in the long run when using generics/interfaces for strongly typed IDs. You could also create a generic StronglyTypedId converter for EF Core.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Good point, I'll see if I can do that in another video

    • @adiviuh3693
      @adiviuh3693 ปีที่แล้ว

      @@MilanJovanovicTech Hello again) After your video about STIDs I've researched this topic and implemented it in my pet project. There are some ready technic for working with this feature. You can find them wonderful to research.
      You can find ready code for ef converters, so you will need to use only builder.HasKey method and builder.Property for telling ef core that props are existing.
      And other features, like json converters default and newtonsoft. Also there is one big problem, that could be solved using a source generator (at least I found it in article), for ToString method.
      So, good lack into self-improvement.

    • @adiviuh3693
      @adiviuh3693 ปีที่แล้ว

      I have another question. I think you have not touched the issue with constructors in EF core context. I think they are the most problematic things.
      So, you need to show people, how to create them. What exactly they could have in case of ef mappings. Why you have to create an additional ctor for ef in some cases, for example then you have a navigation property in ctor.
      How to work with get only props...
      Answers on this questions I've taken by pieces in internet and manual experiments. So it's important points in case of DDD.
      Sorry, for my English 😅

    • @adiviuh3693
      @adiviuh3693 ปีที่แล้ว

      Last question. Do you plan to record videos about microservices and all that staff includes best practices and issues around them? I think it would be a great destination after DDD, clean code and etc. Microservices -> concurrency (at least it's general point of thinking about it, in my opinion).
      You are an amazing person. Thank you for your contribution. 💪

  • @Aweklin
    @Aweklin ปีที่แล้ว +2

    Hi Milan,
    Thanks a million for all the great work on this channel. You are indeed a great role model.
    I love the way you organize your tutorial series. But I want to plead with you to kindly add this order management series to a playlist to make it easy to follow through instead of searching which come next.
    Thanks

  • @bogdanashvets3260
    @bogdanashvets3260 ปีที่แล้ว +1

    Milan, your channel is a treasure :)

  • @mbsa220
    @mbsa220 ปีที่แล้ว +1

    Perfect !
    DDD and EFCore are such a great companion !

  • @tvardero
    @tvardero ปีที่แล้ว +2

    Waiting for EF8 to use structs as value objects )
    Great video!

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I think they have plans to use value converters, we'll see

  • @birukayalew3862
    @birukayalew3862 ปีที่แล้ว +1

    Very awesome ❤ ... i can't wait the next video. Thank you Milan

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Next one will be controversial 😁

    • @birukayalew3862
      @birukayalew3862 ปีที่แล้ว

      @@MilanJovanovicTech I guess it should be about repository pattern?

  • @hkoueke
    @hkoueke ปีที่แล้ว +1

    Right on time. Keep up Milan👍💪

  • @danielegiovanetti9258
    @danielegiovanetti9258 ปีที่แล้ว +1

    Super super super video! Very useful for me. Thanks

  • @Speede04
    @Speede04 ปีที่แล้ว +3

    I wish one time you show us how to configure many-to-many relationship in EF Core with intermediate table and additional data in it ( not for sorting, but for usage :) )

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      Oh, for sure. I'll come up with a goof example first and include it in a future video

  • @Ozarif
    @Ozarif ปีที่แล้ว +1

    Great video Milan, than you.

  • @mihaiga
    @mihaiga ปีที่แล้ว +1

    Great video Milan. My only suggestion is related to ownership of Value Objects: you should not be able to manipulate value objects independent of the Root Aggregate which you can if the value objects have their own EF objects, independent of the root aggregate. If you need to guarantee atomicity when saving the whole aggregate, you could use OwnsMany or OwnsOne when defining the RA Configuration class to specify one:one or one:many relations. However, if a root aggregate has many value objects then the performance can be impacted by "cartesian explosion" scenarios, partially managed by query splitting.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Where did I make value objects to their own objects? 🤔

    • @mihaiga
      @mihaiga ปีที่แล้ว

      @@MilanJovanovicTech You are right, in the video you don't do that. I wanted to add some extra info from my experience with modelling domain entities using EF.

  • @dragannikolic568
    @dragannikolic568 ปีที่แล้ว +6

    Hi Milan, I followed your instructions from the video on small exercise project as I want to improve my skills with your tutorials. Just watching is not enough ;)
    However, when I tried Add-Migration Create_Database in PMC, I got an error:
    No suitable constructor was found for entity type 'LineItem'. The following constructors had parameters that could not be bound to properties of the entity type:
    Cannot bind 'price' in 'LineItem(LineItemId id, OrderId orderId, ProductId productId, Money price)'
    Note that only mapped properties can be bound to constructor parameters. Navigations to related entities, including references to owned types, cannot be bound.
    I had to add empty constructor to LineItem class in order to fix the problem:
    internal LineItem()
    {
    }
    I am puzzled why this happens with EF and why it did not happen in your case. Please if you have time explain what happens, or someone else ca explain too.
    Note: I'm using .NET 7.0.4 libraries and sql server provider

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      Add a private or internal default CTOR and you will be fine. Unfortunate, but you have to do that with EF Core

    • @dragannikolic568
      @dragannikolic568 ปีที่แล้ว

      @@MilanJovanovicTech Thx!

    • @dandoescode
      @dandoescode ปีที่แล้ว +2

      I had the same problem. Thanks guys!

    • @MehediHasan-xd6rj
      @MehediHasan-xd6rj 4 หลายเดือนก่อน +1

      I've faced the same problem. The LineItem's private constructor resolved the issue.

  • @Tamer_Ali
    @Tamer_Ali ปีที่แล้ว +2

    Awesome Milan, you always amazing me 👍
    I hope you talk about object mapping using Mapster or AutoMapper
    Keep going

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Maybe Mapster? I'm not a fan of mapping libraries

    • @Tamer_Ali
      @Tamer_Ali ปีที่แล้ว

      @@MilanJovanovicTech I'm using Mapster. what is the other way you use for mapping and its benefit over libraries? I hope you record a video for it

    • @pilotboba
      @pilotboba ปีที่แล้ว

      I'm coming to agree with those that say these using mappers are an anti-pattern. But, using Mapster with CodeGenration my be a happy medium.

  • @joga_bonito_aro
    @joga_bonito_aro ปีที่แล้ว +2

    Another topic that could be interesting. Mapping domain aggregates/entities to dto and back

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Usually EF Core takes care of that. Only becomes interesting if you have to do it manually.

    • @joga_bonito_aro
      @joga_bonito_aro ปีที่แล้ว

      @@MilanJovanovicTech which happens alot in my cases... maybe i'm doing it wrong >D

  • @volodymyrliashenko1024
    @volodymyrliashenko1024 ปีที่แล้ว +2

    Good, but I didn't get how EF will return an order with LineItems if it has only a getter.
    It should throw except, shouldn't it?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      It can fill in the backing field :)

    • @volodymyrliashenko1024
      @volodymyrliashenko1024 ปีที่แล้ว

      @@MilanJovanovicTech I assume it is going to be implemented as setter.
      If yes, there is no sense to have a separate method to encapsulate adding items to the list.
      How are you going to make it work for EF?

  • @gorannikolic5735
    @gorannikolic5735 ปีที่แล้ว +2

    Great video Milan, just one question, how you would set Max length of the SKU value in the Products table, and how you would create an index on it?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I believe you can do something like Property(p => p.Sku).HasMaxLength or Property(p => p.Sku.Value).HasMaxLength
      Same approach for the index. I think the first one will work because of the define conversion.

  • @GrimReaper160490
    @GrimReaper160490 ปีที่แล้ว +2

    Have you considered generating a course from this DDD series? Thanks for this Milan great stuff as usual :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +2

      Yes, it's going to happen. But I may not start with a DDD course straight away

    • @GrimReaper160490
      @GrimReaper160490 ปีที่แล้ว

      @@MilanJovanovicTech That's fair 😀 looking forward to it

  • @nawarali1912
    @nawarali1912 ปีที่แล้ว +6

    I think we should use a separate set of classes that are responsible for data access and maybe use some libaray to map between the domain models calsses and the data access classes
    greate content
    thanks for your effort

    • @volodymyrliashenko1024
      @volodymyrliashenko1024 ปีที่แล้ว +2

      I feel like this approach (to have a separate entity for the database) would be better in terms of flexibility and simplicity of EF Configuration.

    • @nawarali1912
      @nawarali1912 ปีที่แล้ว +2

      @@volodymyrliashenko1024 yes we can keep our domain models decoupled from the implementation details of the data access layer. This means that if we ever need to switch to a different data access framework, like Dapper, we can do so without affecting the rest of the application all the chages will be in the data access layer.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +4

      In my opinion, it just adds a lot of overhead for not too much of a gain

    • @FranckMercado
      @FranckMercado ปีที่แล้ว +1

      @nawarali1912 that's right because using EF Core, Dapper or any other mapper goes directly against DDD as it ties your domain model to infrastructure. Another approach would be to use your own interface for a mapper and then tie it up to an implementation of your liking. At the end it's a balance that each team would have to decide on.

  • @sachinshrestha2538
    @sachinshrestha2538 9 หลายเดือนก่อน +2

    why dont we have customer propery as navigation in the order entity i dont get it can we have it if want to

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      You can for EF concerns. But DDD says you can't reference other aggregates directly. It will lead to a dirty domain model.

  • @ibrahimfouad6927
    @ibrahimfouad6927 ปีที่แล้ว +1

    Good work keep going.
    But you can handle strongly typed ids with custom value converter to automatically apply conversion from and to database.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      You mean one custom converter for all strongly typed IDs?

    • @ibrahimfouad6927
      @ibrahimfouad6927 ปีที่แล้ว

      @@MilanJovanovicTech Yes exactly one custom generic value converter with base class/record for Strongly typed ids that handles all the conversion automatically.
      You will scan for all strongly typed id by their base then apply the value converter.

  • @Greenthum6
    @Greenthum6 ปีที่แล้ว

    Note that exposing a list as IReadOnlyList does not make the list immutable. The caller can cast it to IList or List and modify the contents freely. I think returning only the enumerator of the list could work as it can be used to create a new list, but not modify the original via it.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I tried casting and it didn't really work as planned

    • @sinemedev7840
      @sinemedev7840 ปีที่แล้ว

      The ToList() creates a shallow copy, so you are fine. Even if someone would take the LineItems and cast it back to List, adding to that list wouldn't affect the original _lineItems List which is used for the database. The proper way would be to use the AsReadOnly method instead of ToList, so public IReadOnlyList LineItems => _lineItems.AsReadOnly();

  • @JesuMarquez
    @JesuMarquez ปีที่แล้ว +1

    Thank's for sharing!
    In your example you use EF but, which will be the approach using ADO?🤔

  • @theveloper3678
    @theveloper3678 8 หลายเดือนก่อน +1

    Awesome Video Milan! 🎉🚀 Thanks for this series
    Did you miss configuring OrderId as fk on lineItem in the LineItemConfiguration on purpose ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน +1

      EF can figure it out by convention most of the time

  • @Maskenken
    @Maskenken หลายเดือนก่อน

    This is really nice. I'm getting CS8618 warnings about the strongly typed ids. It looks like you get the same squiggly lines under the private constructor in the domain. Did you remove this warning in editorconfig?

    • @MilanJovanovicTech
      @MilanJovanovicTech  หลายเดือนก่อน +1

      Yeah, pretty pointless. We need the private ctor for EF, but it warns that some reference types aren't initialized.

    • @Maskenken
      @Maskenken หลายเดือนก่อน

      @@MilanJovanovicTech Thank you. I'm inspired by your approach to C# and teaching. My current project is based on your videos.

  • @harshaghanta1
    @harshaghanta1 ปีที่แล้ว +1

    Hi Milan, For some reason I was getting an error while generating the Migration script. And ended up changing the LineItem class to have the constructors as below.
    public LineItem(LineItemId id, OrderId orderId, ProductId productId, Money price) : this(id, orderId, productId)
    {
    Price = price;
    }
    private LineItem(LineItemId id, OrderId orderId, ProductId productId)
    {
    Id = id;
    OrderId = orderId;
    ProductId = productId;
    }

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      A private parameterless ctor usually works

    • @paisaconmaquina
      @paisaconmaquina 7 หลายเดือนก่อน

      This comment solved my issue, I've spent all day with this. The error is: Cannot bind 'price' in 'LineItem(LineItemId id, OrderId orderId, ProductId productId, Money price)'
      I needed to replace the ctor for LineItem value object:
      from:
      internal LineItem(LineItemId id, OrderId orderId, ProductId productId, Money price)
      {
      Id = id;
      OrderId = orderId;
      ProductId = productId;
      Price = price;
      }
      to: what @harshaghanta1 commented.
      Do you know why does not work the initial ctor?

  • @swift8995
    @swift8995 7 วันที่ผ่านมา

    Why choose HasMany() over OwnsMany()? (Order, LineItems)

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 วันที่ผ่านมา

      Entity vs Value object
      I consider a Line Item to have an identity

  • @isaacayodeji322
    @isaacayodeji322 ปีที่แล้ว +1

    this is sooooooo good

  • @quangdt7181
    @quangdt7181 9 หลายเดือนก่อน

    The value object cannot be replaced by the new record feature. One of reasons is value comparison. But, in any case, I enjoy your video.

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Value comparison is the exact reason to use records. What do you mean?

  • @alpsavasdev
    @alpsavasdev ปีที่แล้ว +1

    Isn't it a simpler and more straightforward approach to map domain entities to database entities via mappers (or in a custom way)? You can have more control over the entity mappings and do not have to deal with the complexity of fluent api?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I don't find the fluent API complex 🤷‍♂️

    • @alpsavasdev
      @alpsavasdev ปีที่แล้ว

      @@MilanJovanovicTech actually I also use fluent api and just asked about comparison to other approach out of curiosity because I haven’t yet tried mapping for data access myself. Thanks for your content, appreciate it 😎

  • @arny6641
    @arny6641 หลายเดือนก่อน

    Hi Milan,
    Thanks for the great video !
    I’m wondering why not configure the LineItems with OwnsMany ?
    In my understanding, an Order should always be fetched with its Items, and a LineItem should not be directly fetched from the database. Am I wrong ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  หลายเดือนก่อน

      Owned entities behave strangely with EF Core, so I'd avoid it. We can configure AutoInclude for navigation properties.

    • @arny6641
      @arny6641 หลายเดือนก่อน

      ​@@MilanJovanovicTech Never heard of AutoInclude before. Thank you for your answer and for teaching so many stuff

  • @10199able
    @10199able ปีที่แล้ว +1

    You used class for Customer, Product, LineItem, Order, but record for Money, Sku (mb I missed something). Should you have used records for all of them? I remember there were some constraints on using records with ef.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +2

      I'm using records where I want structural equality for Value Objects

  • @FranckMercado
    @FranckMercado ปีที่แล้ว +1

    Good video. That's a nice feature of EF Core, although what if you need to change table schemas, database constraints or even another database? You end up limited by EF Core functionality and flexibility.

    • @adiviuh3693
      @adiviuh3693 ปีที่แล้ว

      What do you mean? EF Core could be used with different databases, in general SQL like dbs. EF core also have ability to specify which db schema should be used for your DbContext class or even for your table (you can use second argument of the method ToTable() in EntityTypeBuilder.
      For example, builder.ToTables(”Cats”, schema: "zoo");
      Right now EF Core has a very elegant interface for configuring your db and also has a great performance (than before). Of course these abstractions have some performance troubles, in this case you can use something like Dapper, but I think it has to be used only for specific tasks with requirements of high performance.

    • @FranckMercado
      @FranckMercado ปีที่แล้ว

      @@adiviuh3693 It's fine that EF Core can provide such features, but the purpose of the comment is to depend on your own interfaces and not a specific library interface. If EF Core fits your needs that's alright but if it doesn't you will only find out late in the software life cycle as you will be tied to the library functionality, upgrades, bugs, etc. For small apps I'd say go for it but for bigger, complex ones it's best to depend on your own interfaces.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      You win some, you lose some. Right?

  • @williamdavid508
    @williamdavid508 4 หลายเดือนก่อน

    When the configuration is many-to-many, what can the configuration be like in EF Core? Thank you very much for the video

    • @MilanJovanovicTech
      @MilanJovanovicTech  4 หลายเดือนก่อน +1

      1. Navigations on both sides
      -or-
      2. Join table (entity)

    • @williamdavid508
      @williamdavid508 4 หลายเดือนก่อน

      @@MilanJovanovicTech According to DDD, is it convenient to use navigation from both sides? because in the aggregate we would have to directly associate the other aggregate and not the value object, it is somewhat confusing for me how many to many in DDD and I can hardly find any documentation🥲

  • @danielszopa4303
    @danielszopa4303 ปีที่แล้ว +1

    It is very good video!!!! Keep delivering videos like this! I have one question, I do not want to query for all data from my entity, I want to get user entity without password and others PII data, so I use select method to get only data which I want, but my entity have business logic to defends the entity from creating instance without password, email etc.. Is there any way to deal with it or I need to create some readmodel to choose what I want during query?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Yes - don't store any of that in the User entity to begin with. Better yet, use an external IDP

  • @nawarali1998
    @nawarali1998 9 หลายเดือนก่อน +1

    Great content Thanks for your effort.
    Assuming I have Categories will each product will have multiple categories and each category will contains multiple products which lead to many-to-many relationship my question is assuming I would like to define the Product as an Aggregate root also the Category
    how to break the relation between them using ef-core because we can't reference other aggreagets which lead to keeping only the ids of each one on the other end of the relationship?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      You can make exceptions to any rule. This would be one of them. And this looks more of a CRUD rule than a business rule.

  • @zgembofildzanic8796
    @zgembofildzanic8796 ปีที่แล้ว +1

    Let's say that the customer and order are persisted at the same time to the DB (through a single transaction). How would you then connect those related entities?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      If you think about it, that is unlikely to happen in a real-world scenario.
      But EF should be smart enough to first persist the customer, and then the order, so that referential integrity isnt broken

    • @zgembofildzanic8796
      @zgembofildzanic8796 ปีที่แล้ว

      @@MilanJovanovicTech I agree, customer and order are a horrible example, but I had cases where I have to save connected agregates within the same transaction.

  • @nathansickle1916
    @nathansickle1916 ปีที่แล้ว +1

    How do you handle serialization of strongly-typed IDs (using System.Text.Json or Newtonsoft, either one)? We can create custom converters; however, we would need one for every ID type and there may be many such types.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      You can either map back into ID, or create a simple flag interface and use a custom converter on that

  • @matthewrossee
    @matthewrossee ปีที่แล้ว +1

    What if the value object can be nullable? When configuring conversion in ef core I get an error about using conditional access in an expression, e.g. builder.Property(x => x.SomeProperty).HasConversion(x => x?.Value, value is null ? null : SomeProperty.Create(value)); How do you approach this? Especially if this is a property with other aggregate's Id.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Can it be nullable in DB? Then you need to support that. Either with Null object pattern or making it explicitly null with nullable reference types.

  • @ddreamz94
    @ddreamz94 5 หลายเดือนก่อน

    Hey Milan and thanks for the content. I feel a little bit lost when i have to configure many-to-many relationships. Do you have any suggestions or something I can read in order to learn more how to handle them in the context of DDD?
    Thank you!

  • @Engineer2261
    @Engineer2261 4 หลายเดือนก่อน

    Great content, thanks!

  • @mouradaissani8957
    @mouradaissani8957 ปีที่แล้ว +1

    awesome, no need anymore for Entities Types (Infrastructure), and DDD types Entities Converters (automappers...)

  • @banzeirao
    @banzeirao 3 หลายเดือนก่อน

    unfortunately not work when do a SELECT with a WHERE in entity framework 'could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly'

    • @MilanJovanovicTech
      @MilanJovanovicTech  3 หลายเดือนก่อน

      What did you put in the WHERE statement...

    • @banzeirao
      @banzeirao 3 หลายเดือนก่อน

      @@MilanJovanovicTech after two days of research i discovered that need to be a implicit operator in value object and a primitive cast in LINQ query

  • @kurtdeduytsche7558
    @kurtdeduytsche7558 10 หลายเดือนก่อน +1

    hi milan, great video. just visited your website and wanted to enroll for your clean architecture course, but i'm a poor student and a little too expensive for me. is there a coupon code available i can use so it would be less expensive for me. thanks in advance

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      There's a Black Friday discount running right now

    • @prantobhoumik6586
      @prantobhoumik6586 9 หลายเดือนก่อน

      @@MilanJovanovicTech same ..I am also intern student. 150 dollar is very expensive for me residing at India. So can you please help me by giving any coupon or discount 🥺

  • @murat.yuceer
    @murat.yuceer ปีที่แล้ว +1

    Hi Milan,
    What if you have multiple money field in same entity but share same currency field
    Curreny, Amount, Fee (Amount and Fee is Money but must share same currency)
    How will you map thaT?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Then you would duplicate the currency field, or create another object with multiple amounts and a single currency instance.

    • @murat.yuceer
      @murat.yuceer ปีที่แล้ว

      @@MilanJovanovicTech nice approach

  • @dandoescode
    @dandoescode ปีที่แล้ว +1

    After configuring the Order and LineItem configuration as you've shown, I am getting an EF error when trying to create an order and save it to the Database.
    Unable to cast object of type 'System.Collections.Generic.HashSet`1[DDD.Domain.Orders.LineItem]' to type 'System.Collections.Generic.IReadOnlyList`1[DDD.Domain.Orders.LineItem]'
    Is there additional configuration needed?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Switch the HashSet for a List

    • @dandoescode
      @dandoescode ปีที่แล้ว

      @@MilanJovanovicTech that did the trick. Thanks! Loving the DDD related videos. 😄

  • @mahmoudhelalii4512
    @mahmoudhelalii4512 ปีที่แล้ว

    great effort.
    Could you make a video about elastic search ?

  • @pabloferrando6471
    @pabloferrando6471 ปีที่แล้ว +1

    How would you work with enums, both at domain and EF Configurations? Just to provide an example, let’s say that an Order could be scheduled and have a periodic occurrence which could be expressed by having an Occurrence Value Object. This would be composed by a collection of DaysOfWeek (Monday, Tuesday, etc) and a Perioricity (Weekly, Biweekly, Monthly, etc). How would you store this without recurring to convert the collection into a comma separated string?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Enumes can be stored as integers or strings

    • @pilotboba
      @pilotboba ปีที่แล้ว

      EF inherently supports enums. No specific conversion is needed.

  • @tmstechschool7239
    @tmstechschool7239 10 หลายเดือนก่อน

    thank you, fyi OwnsOne was even part of EF Core 5 I think

  • @microtech2448
    @microtech2448 11 หลายเดือนก่อน +1

    Can we use automapper for this task?

  • @antonmartyniuk
    @antonmartyniuk ปีที่แล้ว +1

    Great video, keep on making a useful stuff.
    Have you tried for a value objects a library ValueOf ? It's a good one with already written boilerplate code.
    In my projects, however I will use a slightly different approach. WebApi layer is always simple and doesn't know anything about your another layers of code. It doesn't know about DDD, strongly typed ids, etc. The same way I will do with database (persistent) layer. So repositories receive and return Dbo objects which are simple and stupid models. Then your services, CQRS handlers map Dbo to corresponding DDD objects. The service and CQRS layers is the most complicated layer in the application so it will benefit from DDD. Again it's how I am doing this

  • @davittonoyan6537
    @davittonoyan6537 ปีที่แล้ว +1

    Hi Milan, how does EF creates object of "Order" when we try to get it from db? Because in order class there is private constructor and properties are private set, there is only create method.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Using the private parameterless ctor that I added in the Order class

    • @davittonoyan6537
      @davittonoyan6537 ปีที่แล้ว

      @@MilanJovanovicTech yes but for example if you want to get orders from Db
      List orders = context.Orders.ToList();
      in this case when EF Reads data from Db it should map it and create objects (Order) right?
      Do you mean that for th ORM mapping it uses Create method that you wrote in Order class?

  • @elpe21
    @elpe21 ปีที่แล้ว +1

    how would you control concurrency? :) would you just add LastModified / RowVersion to domain classes and via EF Core configuration set them as IsConcurrencyToken in EntityTypeConfiguration?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I'd say make a tradeoff and simply use the EF concurrency control mechanism. It's one field in the domain, and maybe you can even make it a private field so it's not exposed.

  • @alfredorodriguez598
    @alfredorodriguez598 ปีที่แล้ว +1

    In the documentation there is an abstract class ValueObject, is it no longer necessary to inherit it to make the valueObjects?

  • @carteja
    @carteja 6 หลายเดือนก่อน

    What if email was a value object and you wanted to use Complex types with an index. How can you map HasIndex on a complex type?

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 หลายเดือนก่อน +1

      From my testing, doesn't seem to be possible to create an index on a complex type through fluent API. That may change in some EF update.

  • @erlimar
    @erlimar ปีที่แล้ว +1

    Top!

  • @furious385
    @furious385 7 หลายเดือนก่อน +1

    How did you do migration with two class lib project ??? if i will try to do something like that i will get error : Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน

      You can specify the target project for the migration

  • @PelFox
    @PelFox ปีที่แล้ว +1

    Theres a common recommendation to not use GUID as your PK (at least not as the clustered index). However, your domain entities should be persistence ignorant and need to be able to generate a unique ID. How do you usually deal with this?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Take a look at EF HiLo, allows you to auto-generate the IDs without hitting the DB

    • @PelFox
      @PelFox ปีที่แล้ว

      @@MilanJovanovicTech Just that MSSQL will by default make your PK clustered index if you do HasKey(), it's not good to use a GUID as the clustered index for your table.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      @@PelFox You can use an int/long as PK + HiLo strategy for EF to generate them without hitting the DB

    • @PelFox
      @PelFox ปีที่แล้ว

      @@MilanJovanovicTech What I've done is keeping the GUID as a "Public ID" and having the int as PK but it's not really used from the consumers. But when using the same model for DDD and Data you will need to have both of these id's, which is persistance logic leaking into the domain model.

  • @dalisaacs
    @dalisaacs ปีที่แล้ว +1

    Hello Milan. Thanks for this awesome training. However i get an error when i run migration... CustomerId requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. Any idea what might be causing this?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Did you miss something? Are you on .NET 7? 🤔

    • @dalisaacs
      @dalisaacs ปีที่แล้ว

      @@MilanJovanovicTech The problem occurs if you don't map the foreign keys correctly of forget to do so. So that was what i did and it is now fix. Thanks.

  • @georgebelletty7861
    @georgebelletty7861 ปีที่แล้ว

    great video

  • @microtech2448
    @microtech2448 11 หลายเดือนก่อน +1

    Should Domain and Persistence not be ignorant to each other, so that they can be updated independent of each other and there should be mapper in some 3rd layer which keeps them mapped?

  • @zbaktube
    @zbaktube ปีที่แล้ว

    Some logic goes to config, and not in the domain model itself. So, if we can add the constrains as attributes + change make an auto configuration according to that...

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      I don't like using attributes

    • @zbaktube
      @zbaktube ปีที่แล้ว

      @@MilanJovanovicTech Hehe, and I totally understand why 🙂 But lets assume we do, and we can mark for example the email field unique. But that check only can happen in your infrastructure, not in your domain. So your domain kind of lack that info. Ok, we can make it Id, but then it has security concerns. We can encode it to hide the content, but then we save the same info twice now. Then, lets put all logic to a third place, and we are now at an anemic model...

  • @microtech2448
    @microtech2448 ปีที่แล้ว +1

    Hi, should our domain entities match exactly with Db tables/columns? If no, then would we end up creating similar/duplicate entities in persistence project?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      I don't think so (when you have a complex domain). I make my entities persistence ignorant, and take care of the mapping with EF

    • @microtech2448
      @microtech2448 ปีที่แล้ว

      @@MilanJovanovicTech thanks

  • @evilroxxx
    @evilroxxx 8 หลายเดือนก่อน

    I have an abstract base class called Entity and have Order, OrderLine and Product derive from it. Now when I run migration it creates a single table called Entity with a type column that includes different values for Order, OrderLine and Product. Instead of this (which is wrong) how do I ensure my EF Core migration will create three tables for Order, OrderLine and Product? I tried this in .NET 5, 6 and 7. Haven't tried 8 yet but I am sure its the same. How to fix this?

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      How did you configure the entities with EF?

    • @evilroxxx
      @evilroxxx 8 หลายเดือนก่อน

      @@MilanJovanovicTech IEntityTypeConfiguration you mean? Using fluent API not using Annotations. Is this an issue? How do you normally do it?

  • @rohit704
    @rohit704 ปีที่แล้ว +1

    What if I want to store currency in a separate table in that case values object will work ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว

      Like a list of currencies?

    • @rohit704
      @rohit704 ปีที่แล้ว

      @@MilanJovanovicTech Yes , want to fetch list of currency from databases.

  • @suryasuresh1106
    @suryasuresh1106 4 หลายเดือนก่อน +1

    Nice

  • @fritzjimenez9109
    @fritzjimenez9109 7 หลายเดือนก่อน

    Is it also good to use annotations? 🤔 specially for relations.

  • @stunna4498
    @stunna4498 ปีที่แล้ว

    what if u had an aggregate root called Player and another one called Team. A player can exist without a team so he would have a nullable field called TeamId? Team id. the Team aggregate root would have a private readonly List _playerIds= new ();
    How would you configure the entity type builder so that when u load a Team he will get the ids of the players inside the _playersIds field in team aggregate root?

  • @ilovepandaypoe6056
    @ilovepandaypoe6056 ปีที่แล้ว +1

    is it possible to use database first with DDD?

  • @mijaelcallejas4406
    @mijaelcallejas4406 10 หลายเดือนก่อน

    but what happened to the database? :(

  • @enciphered7650
    @enciphered7650 ปีที่แล้ว +1

    I still see no point of using a rich domain model. WHY! JUST WHY! All this code and it could just be written in command handlers.

    • @MilanJovanovicTech
      @MilanJovanovicTech  ปีที่แล้ว +1

      Study about domain-centric architectures

    • @enciphered7650
      @enciphered7650 ปีที่แล้ว

      @@MilanJovanovicTech why can't the domain be a collection of request and handers ? I feel like coding the domain in the way you show locks you down while handlers can have pipelines but this can't. So I'm just having a hard time wrapping my head around why anyone would prefer this over that.

  • @techpc5453
    @techpc5453 ปีที่แล้ว +1