The best and well explained DDD series. Just love the entire thing; from presentation to modelling to programming to results. You are really awesome! Thanks a lot Amichai.
Amazing work. It makes a lot of sense to Map directly from the Domain Layer to the database tables, I used an extra step using Mapster, but this is better. Many thanks for this great effort, we really appreciate it.
I really like the series up until now and really appreciate the work and effort you have put up. I do however feel that this episode was a bit rushed. E.g. we could have a more iterative process where we first setup the whole chain and then make sure that a db with a single table was created. Then after we could keep adding to the solution. Now it was so much that we did and could never see the result of until the very end which made it hard to keep up with what exactly we tried to do. Especially in my case where I do something similar and not exactly the same thing made it hard to test if what I am doing corresponds to what you want to achieve. Either way just a bit of feedback but a really great course which I would definitely recommend to other. Keep it up! 💪
Great lesson in a great series! For any other Apple Silicon users, the Docker documentation suggests using azure-sql-edge image, and it worked fine here
This is one of the most detailed video about this topic I've seen (I'm Not counting only YT!) Thank you so much for your efforts and sharing his knowledge (and your bank account password too!)
I think I will be a little more pragmatic than pure. Yes an entity that's internal to an Agg Root could have the same id as another entity in a different Agg Root... However, I will treat all entities (Agg Root) or not as having a unique system wide id. This makes the mapping simpler and also will work if you are using a document database, a relational database or an event store.
I tend to agree, as long as: 1. The aggregates are defined correctly. This includes: 1.1. Entities aren’t shared between aggregates 1.2. Aggregates reference other aggregates by id 1.3. Entities reference other entities by their parent-aggregate’s id. 2. Entity ids are't likely to overlap It’s not uncommon in a DDD codebase that deleting an aggregate affects another aggregate under the hood, following modeling mistakes along the way. This can’t happen if we are strict when defining primary keys.
Very much looking forward to this. I've been working through another "class", but using DDD and CA principals. I ran into a wall when I started to try to configure the DB with complex aggregates. And I couldn't find anything using Google-Fu.
Vladimir Khorikov also has a course on Pluralsight about this, DDD and EF Core 3: Preserving Encapsulation where he talks about how to map your value objects. It's a few years old based on EF Core 3, but still should be relevant. Of course, EF core team keeps saying support for value objects, but it keeps getting pushed out. Supposedly it's on the EF Core 8 roadmap.
Hello, Amichai! I really like your content, especially the DDD series. I have some questions. 1) Why is the HostId a string, but the DinnerId a GUID? 2) Are those going to be foreign keys from their aggregates' tables in the future? Or as we are working with bounded contexts, we prefer to not connect them to their respective tables? 3) What are you planning to cover on the next video? Thanks a lot for your effort!
Thanks, Alexandros! 1. Sometime in the past, I wanted to demonstrate having the host id built as “host_{user-id}” but ended up cutting it. 2. The benefit of using relational databases over document databases is that in the query flow, we can join tables and create read models that don’t correspond to the aggregates. Otherwise, all interactions between aggregates should happen via domain events. To answer your question, you can define them as foreign keys or not, as long as you follow these principles. 3. Domain events 🤙🏼
@@amantinband I can't thank you enough for the content that you share. Considering the answer for the 3rd question I would kindly ask if you could elaborate, or at least explain which options are available, when addressing Domain Events for cases where NoSQL is used and therefore transactions are not typically available. Thank you very much in advance!
I would really like to see some example where you update/edit data existing already. For that matter a simple user registration then some editing of their data. Just make sure it is a bit complex having some owned navigation properties etc. That is where I stuck with ddd frankly because it is all nice to add and delete information but to make modifications I could not find a viable example anywhere on the Internet.
Amazing, thanks a lot, I like the part on how you explain the steps of change the aggregates to database, and explaining why you add incremental id to make sure it's the same dinner id
I did not understand why he added incremental id to make sure it is the same dinner id? Could you explain? I would really appreciate it. Thanks in advance!
I dont get it. Feels like the more we go into this series the more we skip the rules of layered architecture. We install the EF design library into the API lib which makes it now have a relation to how infrastructure handles persistence. Then we start coding in the domain layer so that EF can solve things in the infrastructure layer making us take decision on code related again to how Infrastructure chose to handle persistence. There must be a better way to do this without messing up the whole point of this series or am I missing something?
very good video .Please can you explain more on what you meant between 4:14 & 4:22 ==> that when we're mapping it to the tables that we don't do the following mistakes so we want to make sure that the ID of the entity is not the primary key of that entity table because if it is then
Thanks for the very well explained video, I have a question though: why does the Dbcontext not contain the dbsets for the other entities. What if I want to query the Sections or MenuItems table for read purposes without having to access them from the menus using include?
Your videos are always amazing because of your real hard work and your presentation skill. I have learnt a lot from your videos. I have a query. When I should use EF core's HasMany() method for an aggregate instead of OwnsMany() method? Can you please give one or more real-world examples
I think rather than just reading your code alloud, it would be nice to explain the relationships between the mapping in human terms with examples or visual diagram of the mapping differences with One to many vs Many to one etc than coding terns@@amantinband
@Amichai Why do you prefere composite keys for MenuSection and MenuItem? It seems that only one MenuSectionId and MenuItemId would be enough for primary keys correspondingly. And why do you need MenuId foreign key in MenuItems? It looks like transitive value from the corresponding MenuSection and for me it probably violates relational "normal form".
Since this video is about EF & DDD, I wanted to emphasize the importance of constructing a unique primary key, regardless of the underlying entity id type. Since we are using GUIDs, we should be okay with defining the entity’s id as the primary key, but that is not DDD proof, for the following reason: An entity’s id must be unique within its parent aggregate/entity. This means that we can have multiple aggregates, all with menu sections with identifiers 1-10, and each section with items that have identifiers 1-10. Then, looking at a specific menu item, any definition that does not include the aggregate id (unique across the system) plus the two identifiers will not uniquely identify this menu item. Does that make sense?
@@amantinband It make sense. With the exception of "id must be unique within its parent". Ids are DB realm concept, not object realm one. So IMHO, you should not worry about ids of objects inside an aggreage, just about id of aggregate itself. And within aggregate identity shoud be defined as reference equality. Generally speaking, I would prefere to consider aggregate's object tree as a pure c# concept. May be even making primary key properties shadow.
Thanks for sharing your valuable knowledge. However, it is likely that your db context is only proper for adding rows into db but quite bad for querying with LINQ onto DbSets. For example, what if a host wants to find their guests who attended dinners where were served menus with sections whose name contains "sweets"? This job would be much easier if EF entity model had navigation properties in type of related entities, instead of their ids. I think that happens because all of your aggregate roots are bounded in the context of creating something as all of your codes says. As such, it will be better to move all items in BuberDinner.Domain into BuberDinner.Domain.Creating, which better represents your code purpose.
Shouldn't you use persistence layer (dumb so without logic except maybe the casting/mapping functions)model classes in the persistance layer? And cast the entity objects into the model objects? So you have Request/response objects in the API layer, model objects in the persistance/data layer and entities in the other projects?
One question. What About the performance using Owns Entities? Because those basically auto does include and so, If we have saved a lot of data on the database, our application will be in performance problem! Or not?
Hey man, awesome video, but I’m having trouble accessing your bank account. Can you help? For real though, I have a question. I see a LOT of code first migration databases on YT. Code first seems so limiting to me. What would you do if you need to debug the stored data? Write ad-hoc queries with all the joins? Write a view that does all the same joins as the aggregate? It seems a lot easier to me to write a sql view and point EF at that. Am I missing something there?
Great Content as usual ❤❤ I have a question here if anyone can answer me, if you are only allowed to refrence other aggregates by id then how would you define a many to many relationships in this case? for example if you have a reservation aggregate and user aggregate then you want the reservation aggregate to have list and the user to have list and you can't do that by OwnsMany on both aggregates configs because it will throw an exception. what can you do in that case ?
You are making the best tutorials. Thanks! One question: Is there any CLI command or Visual Studio extension to create `ApplicationDBContext` class automatically from `Models` folder where my model classes are located: 'User', 'Product', 'Account'?
@@amantinband I thought of integrating an Identity provider, something like duende IdentityServer. But creating one sounds really interesting and Id love to do learn that.
Funny and explanatory. Appreciate your efforts. However I still have some missing points on the aggregates issue. Would you re-explain it in different context shortly later on?
Consider creating an AbstractId of T, so that you never forget to create the "Create" method of any Id valueobject any more. public abstract class AbstractId : ValueObject where T : AbstractId { protected AbstractId(Guid value) { Value = value; } public static T Create(Guid guid) => (T)Activator.CreateInstance(typeof(T), guid)!; public Guid Value { get; } public override IEnumerable GetEqualityComponents() { yield return Value; } } and then just use it as follows: public sealed class MenuId : AbstractId { public MenuId(Guid value) : base(value) { } } what do you think about it?
Hello, I ran across your channel these days, very good content! Could you tell me if it's possible to do the mappings between domain entities and tables using a numeric type id attribute in the entities (incremental)? If yes, how?
It is odd that he’s gone near four months without any new content having built a fairly substantial Patreon following. I hope he and his family are ok.
Another awesome video. Thanks for breaking down these topics in such depth. I've been following along with series and every time I think I already know something, you still give me something new! I kept the HostId as a GUID from your domain layer structure video and used the authenticated user's id as the host Id when creating the menu. Was that that intention with this create menu functionality, or are there other plans for how what that HostId should be?
Thanks, Aaron! Somewhere in a past video, I wanted to demonstrate setting the HostId as "Host_{userId}". I ended up cutting that part, but the HostId is still configured that way. You can define the IDs however you like, as long as it follows the DDD principles of ID uniqueness
Great series wish you good continuation, I have one question what if I want to use (int Id) as primary key for all my domain entities , which is given by the persistence layer .
Amazing video Amichai! Have you ran upon an issue where DinnerId is configured both as a property on Dinners table and a collection of owned entity types on Menu (MenuDinnerIds) which then causes a NRE upon add migration if Dinner aggregate also contains owned entity type(s)?
Great video really as all the series so far. Just a question: looking at the changes you did to the domain model to success in the migration phase (parameterless constructor, private set,.. ) wouldn't be better to create a datamodel in the infrastructure layer with navigation properties for example isolated from the domain model and use mapster to map between them ?
Thanks, Manlio! This is indeed where the theory hits reality, and we need to make changes to our domain layer to support persistence. I don't think it's worth another layer of abstraction since we aren't exposing properties or changing our domain-model logic for infra concerns. The configuration file per aggregate *is* the mapping between the aggregate and the database. It is flexible and allows configuring the tables to look however we want. Is maintaining another set of classes alongside our domain and having a configuration file on top of that better than adding private setters and private ctors? Personally, no.
Рік тому
Amichai congratulations for the video. Very instructive. A quick question. Are the changes made to the domain model compatible for using a document database like Mongo DB? Will we have an example similar to this using a NoSQL database?
I'm not Amichai, but a couple of years ago, I did something similar (not fully DDD) migrating some data from MySQL to CosmosDB, and only did changes in the (back then) classes related to write to the database. I suppose all the changes would be made in the Infrastructure Layer in this case. IN THEORY should be easier, since MongoDB I suppose, could store a document per entity.
Thanks, Jordi 🙏🏻 There shouldn't be an issue mapping our aggregates to a document database (the configurations needed differ based on the database provider you choose). As Carlos wrote, fewer configurations will probably berequiredd.
Hey, while i was watching the content, it came to me a legit question. Is DDD just db first approach with few things more, or I don't get the point? :) thanks a lot
I see that the DDD entities and the DB's tables match. Does that mean that mostly they should match? At what scenarios the DDD entities and EF's entities differ?
They don't necessarily match. Using EF Core, we can define the tables however we see fit. For example, a good alternative to what we did today would have been to store the sections and section items as JSON instead of owned entities.
Thanks for amazing series! How much can we pay over the patreon to separate you from Microsoft and get you as full-time to complete this series quicker? 😁
I really do Not like the fact that i have to mess with the parameterless ctors and the private Setters in the core project because of an implementation detail . But i See that this is the pragmatic part of the story.
What your thoughts on Guid vs Int as entity key? I can think of a dozen reasons why use a Guid... is there any reason at all to even consider the old school auto increment int?
Sounds like performance is the only advantage that i have observed. I switched to Guids almost a decade ago... so many advantages, especially now that Cloud and the move away from a single DB solution is here.
@@brookster7772 If you are using SQL Server you may want to look into sequential guids if you haven't already. Main issue I saw with guids was when doing massive inserts with random values, due to the clustered index page splits. Sequential guids keep the page splits from happening, so you end up with performance that is pretty close to using a long.
I think Persistence ignorance rule can be easily ignored when you adopt db-first approach. Another issue would be it wouldn't be easy to handle conflicts, if any, between domain entities and those scaffolded by ef core.
Thanks for this massive effort! Child entities must have identifiers that are (at least) locally unique. "Child entities must have identifiers that are only locally unique" is completely different. Child entity identifiers never need to be (or should be) exposed, except to the parent. These composite keys scream out, "I know I am being persisted and that I require a globally unique identifier!" This seems to introduce unnecessary complexity and persistence knowledge to the domain. Why?
So following this series was great up to this point. I am unable to finish it because my code generates so many errors while trying to create Menus migration. I have createated other aggregates and was able to create a migration. I followed your code to the letter and had some problems: 1. Average rating could not bo mapped into the table because it had no Id, so i had to ignore it in OnModelCreating method. 2. Error: "The 'MenuId' property 'MenuItem.MenuId' could not be mapped because the database provider does not support this type. " is what's haunting me. I am unable to resolve it in any way. All my Id value objects are correct (with private setters and constructors). What i am missing? Any1 can help?
The first issue sounds like you might have used ".HasOne()" instead of ".OwnsOne()". For the second issue, i was just able to follow this video🤷♀The MenuItem class shouldn't have a C# property MenuId in your code, it's only in the configuration.
What if you don't want to load all related items of some object, say if you have a youtube video with likes and you don't want to load thousands of records from the database. The aggregate root is supposed to always be retrieved as a whole so what happens if that's too much data?
If you are loading too much data when retrieving the aggregate root then you should reconsider your aggregate design. The aggregate must be as small as possible.
Amazing Content!. Keep it up. I have a small question: Is the aggregate pattern only bound to DDD?. Can I not just use the aggregate pattern within a clean architecture design but still implement my business logic without using Domain events etc..
Thank you a lot, this video is wonderful. I have a question and I hope you can help me to understand. Why did not use a field such as HostId to save the actual value of the primary key for MenuSections and MenuItems tables? and Why did you map directly the ids of json to the primaray keys of the tables MenuSections and MenuItems? I remember that you said "the MenuId, MenuSectionId and MenuItemId in your Domain are value objets and inside of them is saved the actual value such as a property". I think that if you do such as you said in your in your video at minute 10:10 you couldn't have the same ids for MenuSection and MenuItem in two differents aggregates, I mean you could not repet the id of the entities MenuSection and MenuItem in two differentes aggragates
Thanks, Erik! Defining entity IDs as value objects allows changing the underlying id type without having to also update all other entities that have reference to this ID. If you update the ID type (for example, from GUID to string), you'd need to only update the ID value object and maybe also the mapping of this ID to the database, which would result in another migration. Does that make sense?
The best and well explained DDD series. Just love the entire thing; from presentation to modelling to programming to results.
You are really awesome!
Thanks a lot Amichai.
Amazing work. It makes a lot of sense to Map directly from the Domain Layer to the database tables, I used an extra step using Mapster, but this is better.
Many thanks for this great effort, we really appreciate it.
Brilliant video. Waiting for more interesting videos in 2023.
I really like the series up until now and really appreciate the work and effort you have put up. I do however feel that this episode was a bit rushed. E.g. we could have a more iterative process where we first setup the whole chain and then make sure that a db with a single table was created. Then after we could keep adding to the solution. Now it was so much that we did and could never see the result of until the very end which made it hard to keep up with what exactly we tried to do. Especially in my case where I do something similar and not exactly the same thing made it hard to test if what I am doing corresponds to what you want to achieve. Either way just a bit of feedback but a really great course which I would definitely recommend to other. Keep it up! 💪
Great lesson in a great series!
For any other Apple Silicon users, the Docker documentation suggests using azure-sql-edge image, and it worked fine here
This is my first viewed video for this chaine, May 2, 2023. Excellent video series, you make hard word . Continue like this.
Hi Amichai! How would you do many to many relationship? To me, it seems rather tricky
This is one of the most detailed video about this topic I've seen (I'm Not counting only YT!) Thank you so much for your efforts and sharing his knowledge (and your bank account password too!)
I think I will be a little more pragmatic than pure. Yes an entity that's internal to an Agg Root could have the same id as another entity in a different Agg Root... However, I will treat all entities (Agg Root) or not as having a unique system wide id. This makes the mapping simpler and also will work if you are using a document database, a relational database or an event store.
I tend to agree, as long as:
1. The aggregates are defined correctly. This includes:
1.1. Entities aren’t shared between aggregates
1.2. Aggregates reference other aggregates by id
1.3. Entities reference other entities by their parent-aggregate’s id.
2. Entity ids are't likely to overlap
It’s not uncommon in a DDD codebase that deleting an aggregate affects another aggregate under the hood, following modeling mistakes along the way. This can’t happen if we are strict when defining primary keys.
Love your concentrated videos so much. Have to pause them all the time)) plz go on
Very much looking forward to this. I've been working through another "class", but using DDD and CA principals. I ran into a wall when I started to try to configure the DB with complex aggregates. And I couldn't find anything using Google-Fu.
Hopefully this video gives you clarity on the topic 🙂 Let me know!
Vladimir Khorikov also has a course on Pluralsight about this, DDD and EF Core 3: Preserving Encapsulation where he talks about how to map your value objects. It's a few years old based on EF Core 3, but still should be relevant.
Of course, EF core team keeps saying support for value objects, but it keeps getting pushed out. Supposedly it's on the EF Core 8 roadmap.
Hello, Amichai! I really like your content, especially the DDD series.
I have some questions.
1) Why is the HostId a string, but the DinnerId a GUID?
2) Are those going to be foreign keys from their aggregates' tables in the future? Or as we are working with bounded contexts, we prefer to not connect them to their respective tables?
3) What are you planning to cover on the next video?
Thanks a lot for your effort!
Thanks, Alexandros!
1. Sometime in the past, I wanted to demonstrate having the host id built as “host_{user-id}” but ended up cutting it.
2. The benefit of using relational databases over document databases is that in the query flow, we can join tables and create read models that don’t correspond to the aggregates. Otherwise, all interactions between aggregates should happen via domain events. To answer your question, you can define them as foreign keys or not, as long as you follow these principles.
3. Domain events 🤙🏼
@@amantinband I can't thank you enough for the content that you share. Considering the answer for the 3rd question I would kindly ask if you could elaborate, or at least explain which options are available, when addressing Domain Events for cases where NoSQL is used and therefore transactions are not typically available. Thank you very much in advance!
I would really like to see some example where you update/edit data existing already. For that matter a simple user registration then some editing of their data. Just make sure it is a bit complex having some owned navigation properties etc. That is where I stuck with ddd frankly because it is all nice to add and delete information but to make modifications I could not find a viable example anywhere on the Internet.
What a content.. well explained and straight to the point!! Thank you so much
My God! So blessed to found this channel! the best .NET Teacher! Thank you!
Amazing, thanks a lot, I like the part on how you explain the steps of change the aggregates to database, and explaining why you add incremental id to make sure it's the same dinner id
I did not understand why he added incremental id to make sure it is the same dinner id? Could you explain? I would really appreciate it. Thanks in advance!
What program is being used to visualize/describe your code and database? That would be nice to use during demos with the higher ups at work!
I dont get it. Feels like the more we go into this series the more we skip the rules of layered architecture. We install the EF design library into the API lib which makes it now have a relation to how infrastructure handles persistence. Then we start coding in the domain layer so that EF can solve things in the infrastructure layer making us take decision on code related again to how Infrastructure chose to handle persistence. There must be a better way to do this without messing up the whole point of this series or am I missing something?
Amazing and Detailed work and explanation !!! I appreciate your time and dedication to create content like this...
Hello from Honduras.
Love it man. You really inspire us. Really looking foward to the full crud.
Amazing secure password, very safe and hard to guess!! Thanks for trusting us with it
Thank you for the amazing and informative video! Your concise explanations helped me learn a lot.
How is inserting a Menu with HostId gonna populate HostMenuIds table? Are we supposed to fill it with data in repository manually?
Is there a source repo for this? Would love to look at the final result.
very good video .Please can you explain more on what you meant between 4:14 & 4:22 ==> that when we're mapping it to the tables that we don't do the following mistakes so we want to make sure that the ID of
the entity is not the primary key of that entity table because if it is then
Amazing Video! I'm just confusing about the reason why the HostId FK wasn't been created
thanks for the great information Amichai. you've done a great things.
First off thank you so much for sharing this knowledge.
I do have a question, how do you prevent the models from having circular dependencies.
Thanks for the very well explained video, I have a question though: why does the Dbcontext not contain the dbsets for the other entities. What if I want to query the Sections or MenuItems table for read purposes without having to access them from the menus using include?
Your videos are always amazing because of your real hard work and your presentation skill. I have learnt a lot from your videos. I have a query. When I should use EF core's HasMany() method for an aggregate instead of OwnsMany() method? Can you please give one or more real-world examples
The editing in this video is amazing. Did you do it all yourself?
Yup, he did it himself! This is really great editing in my opinion too :)
Hey Milan - love your content too!!😁
It would be great if you talk more about the communication between bounded contexts when applied DDD with EF Core.
What specifically would you like to see?
I think rather than just reading your code alloud, it would be nice to explain the relationships between the mapping in human terms with examples or visual diagram of the mapping differences with One to many vs Many to one etc than coding terns@@amantinband
Great video, and a great playlist. Thanks and We are waiting for your next videos
Great video. Just a thought, how about DB first approach to setup such things initially?
Useful and informative content as usual. Thank you!
@Amichai Why do you prefere composite keys for MenuSection and MenuItem? It seems that only one MenuSectionId and MenuItemId would be enough for primary keys correspondingly. And why do you need MenuId foreign key in MenuItems? It looks like transitive value from the corresponding MenuSection and for me it probably violates relational "normal form".
Since this video is about EF & DDD, I wanted to emphasize the importance of constructing a unique primary key, regardless of the underlying entity id type. Since we are using GUIDs, we should be okay with defining the entity’s id as the primary key, but that is not DDD proof, for the following reason:
An entity’s id must be unique within its parent aggregate/entity. This means that we can have multiple aggregates, all with menu sections with identifiers 1-10, and each section with items that have identifiers 1-10.
Then, looking at a specific menu item, any definition that does not include the aggregate id (unique across the system) plus the two identifiers will not uniquely identify this menu item.
Does that make sense?
@@amantinband It make sense. With the exception of "id must be unique within its parent". Ids are DB realm concept, not object realm one. So IMHO, you should not worry about ids of objects inside an aggreage, just about id of aggregate itself. And within aggregate identity shoud be defined as reference equality. Generally speaking, I would prefere to consider aggregate's object tree as a pure c# concept. May be even making primary key properties shadow.
When mapping an inheritance hierarchy in DDD, do you recommend STI or CTI?
Thanks for sharing your valuable knowledge.
However, it is likely that your db context is only proper for adding rows into db but quite bad for querying with LINQ onto DbSets.
For example, what if a host wants to find their guests who attended dinners where were served menus with sections whose name contains "sweets"?
This job would be much easier if EF entity model had navigation properties in type of related entities, instead of their ids.
I think that happens because all of your aggregate roots are bounded in the context of creating something as all of your codes says.
As such, it will be better to move all items in BuberDinner.Domain into BuberDinner.Domain.Creating, which better represents your code purpose.
awesome series, lot of efforts, really appreciated!! thanks for amazing series!!!
Is it good practice to define MaxLength in the database tables configuration? Shouldn"t the (fluent) validation check this in the application layer?
Shouldn't you use persistence layer (dumb so without logic except maybe the casting/mapping functions)model classes in the persistance layer? And cast the entity objects into the model objects? So you have Request/response objects in the API layer, model objects in the persistance/data layer and entities in the other projects?
One question. What About the performance using Owns Entities? Because those basically auto does include and so, If we have saved a lot of data on the database, our application will be in performance problem! Or not?
Hey man, awesome video, but I’m having trouble accessing your bank account. Can you help?
For real though, I have a question. I see a LOT of code first migration databases on YT.
Code first seems so limiting to me.
What would you do if you need to debug the stored data? Write ad-hoc queries with all the joins? Write a view that does all the same joins as the aggregate?
It seems a lot easier to me to write a sql view and point EF at that.
Am I missing something there?
do you have domain events video? what is your opinion on transaction cross aggregate? Thanks,
Great Content as usual ❤❤
I have a question here if anyone can answer me, if you are only allowed to refrence other aggregates by id then how would you define a many to many relationships in this case?
for example if you have a reservation aggregate and user aggregate then you want the reservation aggregate to have list and the user to have list and you can't do that by OwnsMany on both aggregates configs because it will throw an exception. what can you do in that case ?
I really like the password... I also plan to use it across all my accounts :)
Thanks for great video's :)
Clearest mind ever I seen!
You are making the best tutorials. Thanks!
One question: Is there any CLI command or Visual Studio extension to create `ApplicationDBContext` class automatically from `Models` folder where my model classes are located: 'User', 'Product', 'Account'?
Love this series! Are you planning on making a video about setting up an Identity server?
Appreciate the content
Thanks Zydra! Do you mean integrating with an identity provider? Or creating an identity provider?
@@amantinband I thought of integrating an Identity provider, something like duende IdentityServer. But creating one sounds really interesting and Id love to do learn that.
We'll cover integration in a future video 👍🏼
@@amantinband Awsome! Looking forward to the video.
Nice! Will You also add guests and other aggregates to DB?
Funny and explanatory. Appreciate your efforts. However I still have some missing points on the aggregates issue. Would you re-explain it in different context shortly later on?
Brilliant as usual - really detailed.
Thank you 🙏🏼
What is the software used for this beautiful presentation/session 😅
Consider creating an AbstractId of T, so that you never forget to create the "Create" method of any Id valueobject any more.
public abstract class AbstractId : ValueObject
where T : AbstractId
{
protected AbstractId(Guid value)
{
Value = value;
}
public static T Create(Guid guid) => (T)Activator.CreateInstance(typeof(T), guid)!;
public Guid Value { get; }
public override IEnumerable GetEqualityComponents()
{
yield return Value;
}
}
and then just use it as follows:
public sealed class MenuId : AbstractId
{
public MenuId(Guid value) : base(value)
{
}
}
what do you think about it?
Hello, I ran across your channel these days, very good content!
Could you tell me if it's possible to do the mappings between domain entities and tables using a numeric type id attribute in the entities (incremental)? If yes, how?
How do you get these suggestions in your CLI ?😮
Hey, this is great! Will you be releasing new videos in this series any time soon?
It is odd that he’s gone near four months without any new content having built a fairly substantial Patreon following. I hope he and his family are ok.
You're THA man! Nice video, learned a lot. Thanks!
Another awesome video. Thanks for breaking down these topics in such depth. I've been following along with series and every time I think I already know something, you still give me something new! I kept the HostId as a GUID from your domain layer structure video and used the authenticated user's id as the host Id when creating the menu. Was that that intention with this create menu functionality, or are there other plans for how what that HostId should be?
Thanks, Aaron!
Somewhere in a past video, I wanted to demonstrate setting the HostId as "Host_{userId}". I ended up cutting that part, but the HostId is still configured that way. You can define the IDs however you like, as long as it follows the DDD principles of ID uniqueness
Great series wish you good continuation, I have one question what if I want to use (int Id) as primary key for all my domain entities , which is given by the persistence layer .
Amazing video Amichai! Have you ran upon an issue where DinnerId is configured both as a property on Dinners table and a collection of owned entity types on Menu (MenuDinnerIds) which then causes a NRE upon add migration if Dinner aggregate also contains owned entity type(s)?
i got the same problem did you find any solution for it
@@nawarali1912 I also have an same error
I forgot add 'private set;' and it's working too :).
Great video really as all the series so far. Just a question: looking at the changes you did to the domain model to success in the migration phase (parameterless constructor, private set,.. ) wouldn't be better to create a datamodel in the infrastructure layer with navigation properties for example isolated from the domain model and use mapster to map between them ?
Thanks, Manlio!
This is indeed where the theory hits reality, and we need to make changes to our domain layer to support persistence.
I don't think it's worth another layer of abstraction since we aren't exposing properties or changing our domain-model logic for infra concerns.
The configuration file per aggregate *is* the mapping between the aggregate and the database. It is flexible and allows configuring the tables to look however we want. Is maintaining another set of classes alongside our domain and having a configuration file on top of that better than adding private setters and private ctors? Personally, no.
Amichai congratulations for the video. Very instructive. A quick question. Are the changes made to the domain model compatible for using a document database like Mongo DB? Will we have an example similar to this using a NoSQL database?
I'm not Amichai, but a couple of years ago, I did something similar (not fully DDD) migrating some data from MySQL to CosmosDB, and only did changes in the (back then) classes related to write to the database. I suppose all the changes would be made in the Infrastructure Layer in this case. IN THEORY should be easier, since MongoDB I suppose, could store a document per entity.
Thanks, Jordi 🙏🏻
There shouldn't be an issue mapping our aggregates to a document database (the configurations needed differ based on the database provider you choose). As Carlos wrote, fewer configurations will probably berequiredd.
It is very useful, but I cannot find the code on your github. can you share the code with us?
I thought aggregate was stuff you used when building houses, or driveways and such things. It would be nice to know what it is in plain english
You almost never use interfaces. Is it not better to use IList on aggregates?
Hey, while i was watching the content, it came to me a legit question. Is DDD just db first approach with few things more, or I don't get the point? :) thanks a lot
I see that the DDD entities and the DB's tables match. Does that mean that mostly they should match? At what scenarios the DDD entities and EF's entities differ?
They don't necessarily match. Using EF Core, we can define the tables however we see fit. For example, a good alternative to what we did today would have been to store the sections and section items as JSON instead of owned entities.
thanks for your efforts i really appreciate it
Thanks for amazing series!
How much can we pay over the patreon to separate you from Microsoft and get you as full-time to complete this series quicker? 😁
I really do Not like the fact that i have to mess with the parameterless ctors and the private Setters in the core project because of an implementation detail . But i See that this is the pragmatic part of the story.
Same. That's where theory and reality meet.
can we make the relationship inside the domain entity instead of using the ientityconfiguration?
Yes, although this breaks the clean architecture logical structure we created since you would now have persistence logic in your domain layers.
What your thoughts on Guid vs Int as entity key? I can think of a dozen reasons why use a Guid... is there any reason at all to even consider the old school auto increment int?
Smaller key, smaller indexes, faster queries
Yup, what Eirenarch said
Sounds like performance is the only advantage that i have observed. I switched to Guids almost a decade ago... so many advantages, especially now that Cloud and the move away from a single DB solution is here.
@@brookster7772 If you are using SQL Server you may want to look into sequential guids if you haven't already. Main issue I saw with guids was when doing massive inserts with random values, due to the clustered index page splits. Sequential guids keep the page splits from happening, so you end up with performance that is pretty close to using a long.
Nice video with content and great explanation. May I know the tool for creating the graphics and the video ?
He uses Figma 🙂
complete your project > nice channel
Can’t wait ❤❤
Is it possible to use DDD and database first? Also CA is only best with Model First?
I think Persistence ignorance rule can be easily ignored when you adopt db-first approach.
Another issue would be it wouldn't be easy to handle conflicts, if any, between domain entities and those scaffolded by ef core.
love your content, thank you A LOT
Thanks for this massive effort!
Child entities must have identifiers that are (at least) locally unique.
"Child entities must have identifiers that are only locally unique" is completely different.
Child entity identifiers never need to be (or should be) exposed, except to the parent.
These composite keys scream out, "I know I am being persisted and that I require a globally unique identifier!"
This seems to introduce unnecessary complexity and persistence knowledge to the domain.
Why?
Amazing work!
Legend, amazing content thanks again :)
Glad you enjoyed it!
This is pure gold’
I've checked your bank account. Thanks a lot for the money
So following this series was great up to this point. I am unable to finish it because my code generates so many errors while trying to create Menus migration. I have createated other aggregates and was able to create a migration. I followed your code to the letter and had some problems:
1. Average rating could not bo mapped into the table because it had no Id, so i had to ignore it in OnModelCreating method.
2. Error: "The 'MenuId' property 'MenuItem.MenuId' could not be mapped because the database provider does not support this type. " is what's haunting me. I am unable to resolve it in any way. All my Id value objects are correct (with private setters and constructors).
What i am missing? Any1 can help?
The first issue sounds like you might have used ".HasOne()" instead of ".OwnsOne()". For the second issue, i was just able to follow this video🤷♀The MenuItem class shouldn't have a C# property MenuId in your code, it's only in the configuration.
Please publish this whole solution to Azure environment with App Service, Azure SQL, Key Vault etc. and make video of that too.
Some of those topics are already planned 🙂
What if you don't want to load all related items of some object, say if you have a youtube video with likes and you don't want to load thousands of records from the database. The aggregate root is supposed to always be retrieved as a whole so what happens if that's too much data?
If you are loading too much data when retrieving the aggregate root then you should reconsider your aggregate design.
The aggregate must be as small as possible.
Have you watched my video on modeling the domain layer? As Tarek wrote, this is one of the reasons we want smaller aggregates rather than bigger ones.
@@amantinband OK so a post like is an aggregate root? I find this hard to imagine.
Yup. If you'll search for an entity by ID, it's usually a sign the entity should be an aggregate
Thanks a lot for your content
Amazing Content!. Keep it up. I have a small question: Is the aggregate pattern only bound to DDD?. Can I not just use the aggregate pattern within a clean architecture design but still implement my business logic without using Domain events etc..
You can still use the aggregate design. DDD only applies when you specify behiavor and actions within your aggregates/entities.
Waiting for it...
Great atuff. Thanks
Can you make video about Unit tests
It's planned 👍🏻
thank you, can you provide the source code please?
Thanks Arras, the source code is available for my patrons (it's 5$)
Thank you!
Good video !!!
Thanks Diego 🫶🏼
Excellent
Thank you a lot, this video is wonderful. I have a question and I hope you can help me to understand. Why did not use a field such as HostId to save the actual value of the primary key for MenuSections and MenuItems tables? and Why did you map directly the ids of json to the primaray keys of the tables MenuSections and MenuItems? I remember that you said "the MenuId, MenuSectionId and MenuItemId in your Domain are value objets and inside of them is saved the actual value such as a property". I think that if you do such as you said in your in your video at minute 10:10 you couldn't have the same ids for MenuSection and MenuItem in two differents aggregates, I mean you could not repet the id of the entities MenuSection and MenuItem in two differentes aggragates
Thanks, Erik!
Defining entity IDs as value objects allows changing the underlying id type without having to also update all other entities that have reference to this ID.
If you update the ID type (for example, from GUID to string), you'd need to only update the ID value object and maybe also the mapping of this ID to the database, which would result in another migration.
Does that make sense?
Please how can I reach you ?
I’ve sent you a message on Twitter
Answered 🙂
Good Stuff!
(Edit: "Nah great stuff")
very nice