EF Core 8 Finally Fixes Value Objects

  Рет қаралды 26,070

Milan Jovanović

Milan Jovanović

Күн бұрын

Пікірлер: 125
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@Dpaz2009
@Dpaz2009 10 ай бұрын
Thank you!
@kumailn7662
@kumailn7662 9 ай бұрын
why programming with C# is becoming complex. !!
@reelleer
@reelleer Жыл бұрын
Dicha funcionalidad existía en EF 6, por lo tanto ver que EF Core 8 ya la tiene me motiva a migrar mi aplicación "legacy".
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yep, old EF features coming to EF Core
@ahmedh2482
@ahmedh2482 5 ай бұрын
Doesn't this lead to redundancy in the database?!, I mean object values Why you don't use the author id instead of author object? Then you can use dto or anything to deal with your needs without overburden the database
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
Is redundancy always bad?
@ahmedh2482
@ahmedh2482 5 ай бұрын
@@MilanJovanovicTech Suppose I'm trying to build a software for a distribution company (FMCG company), When the data entry or sales representative try to create an invoice He should determine the following The store: where the goods located, The salesman: the person who sold, The customer,... Each of the previous entities have at least 5 to 10 properties, Why I build a table in the database contains about 35 columns and most of them duplicate?
@skelaw
@skelaw 4 ай бұрын
​​@@ahmedh2482 to preserve historical data at particullar point of time. I always store simillar info you listed in order/invoice etc. Those informations belongs to document and this is not redundant to store them, its required.
@jakelanning1535
@jakelanning1535 3 ай бұрын
Why not have an author entity and let book have an author id column with a foreign key into the authors table modelBuilder.Entity() .HasOne() .WithMany(e => e.Books) .HasForeignKey(e => e.AuthorId) .IsRequired(); Book's `public Author Author` would become `public virtual Author Author` and, as previously stated, would need a `public int AuthorId` and Author would need to have a `public virtual ICollection Books` as well as a `public int Id` I understand this is an example just to show off the feature, but i just can't imagine any case where using .OwnsOne makes more sense than to use a separate entity with a navigation property enabled by a foreign key, especially if theres a chance that the owned entity might be used in multiple of the parent entities. are joins evil and no one told me?
@MilanJovanovicTech
@MilanJovanovicTech 3 ай бұрын
Just showcasing an EF feature here :) We're not talking about relational design 101.
@fandermill
@fandermill Жыл бұрын
Changing the last name of the author and updating it in all books does not make sense, as ValueObjects should be immutable (well, at least from a DDD perspective). Nice feature demo though, I can't wait to clean up my dbcontext configurations.
@ahmedrizk106
@ahmedrizk106 Жыл бұрын
I think it makes perfect sense if you are making the change on the shared author instance, but if you are making the change on the book instance it self it should not affect any other records.
@Code_Bits
@Code_Bits Жыл бұрын
And also using the with statement means it would set the value bypassing any guard clauses if they would be there. I'm not a fan of using Records for ValueObjects.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I needed a super simple example to showcase the features, so I had to "dumb" it down
@sunzhang-d9v
@sunzhang-d9v Жыл бұрын
class ->record ,yes?
@hanneskasel1853
@hanneskasel1853 6 ай бұрын
hmm yeah sharing instance is also not recommended whereas you shall make the complex type immutable
@MilanJovanovicTech
@MilanJovanovicTech 6 ай бұрын
This was more about showcasing what Complex types can do, though
@psdmaniac
@psdmaniac Жыл бұрын
I have never used that. Autors should be stored is diffrent table and reused (many to many). This "own" thing looks like something against database normalization.
@antonmartyniuk
@antonmartyniuk Жыл бұрын
It is indeed against database normalisation. But there are certainly cases when you need to sacrifice this in favor of performance
@glennmerrill88ify
@glennmerrill88ify Жыл бұрын
​@antonmartyniuk Like when? I don't see a single reason to not normalize the example shown. Why would you want a bunch of anomalies littered around your database ever?
@antonofka9018
@antonofka9018 Жыл бұрын
​It's going to be one less join when you query, which can be a big deal
@psdmaniac
@psdmaniac Жыл бұрын
Books and autors and you don't see why It should be normalized? Realy :)? What If you need to display list of autors? Will you sellect all books records and make district on autors? What if someone ask you to genereate more advance report, Daily? What about performance now :)? The solutuon is 1. Always keep your db normalized 2. Violate point 1 only if it is realy needed. For example some data redundancy is needed. And even of needed in longer period of time this bacame problematic (multiple points of truth).
@antonmartyniuk
@antonmartyniuk Жыл бұрын
@@psdmaniac we aren't talking specifically about this concrete example of books/authors with data normalisation. And besides, this data shape is completely valid in NoSQL world and apps have no problems with this approach
10 ай бұрын
It's not yet full supported. Complex type collection support is not ready. Check the issue 31237 and vote!
@MilanJovanovicTech
@MilanJovanovicTech 10 ай бұрын
There's ways around that for the time being
10 ай бұрын
@@MilanJovanovicTech You could show an example of this in your videos. I am currently following Amichai's workarround "The Identity Paradox | DDD, EF Core & Strongly Typed IDs", although I don't like the arrangement too much because there is actually a small leak in the domain model that causes difficulties with the ids if it is being used the repository pattern with specification. On the other hand, I have tried creating a data model and mapping it to the domain model, but it seems like too much effort to maintain synchronization between both models. Additionally, the Id collections of my domain model are of type readonly collection. So instantiating it with automapper and EF is difficult for me and I don't think using reflection is the way to go. I look forward to your solution. Greetings :)
@_IGORzysko
@_IGORzysko Жыл бұрын
Thanks for the video Milan! The possibility o fetching only value object data from the table is really great 🔥 Are EF 8 value objects tracked the same as "entity" entities? 🤔
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yes, they're tracked by EF
@MikyShooter
@MikyShooter Жыл бұрын
For all that says this example does not suit the feature, you may be right. It doesn't metter but the explication, that was imo exaustive. Here is another simple example: In case of an order we may have a shipping address related to it. It's not ideal to save the Id of the customer address but the information itself at time t. This because the address could potentially be removed from the customer entity, or even modified. Best thing is to store it separately, as this case, in a complex object, also to sepate concerns in class. Thank you Milan for all your videos.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Very good example with order + shipping address ✅
@jeroen7362
@jeroen7362 Жыл бұрын
The order with shipping addres as mentioned here could be a scenario. Still i would not use it for that. Just add a few fields to the order for the address, postal code and town, country and done. probably country would be a foreign key to the country table. The actual up to date address would be stored in a address table that is referenced by the customer class. This is the address you would show for next checkout and in their profile.
@MikyShooter
@MikyShooter Жыл бұрын
@@jeroen7362 With complex objects, as explained by Milan and by the docs, are still created in the same table. No need to add in the same class. In code side they are wrapped in a class but in db they are on the same table as "Type_PropertyName", so no need to have a class with many properties that could be easly the wrapped. For this particular scenario I would not relate shipping address to profile address since: - profile address could be changed but shipping address in order not. (maybe I moved out of the parents house and update the profile address, but the shipping address should be the same as choosed in the creation contract). Any updates should be done separately, also with other kind of process (for courier). For instance one moves from europe to america, and update the profile address, but the order is shipped so the address should be the one in europe and not let the courier be in entropy. - by referencing profile address in order, you don't have consistency on the history side: at time t1 was with address1 and at t2 with address2, and not t1 with address2 (with reference and not value). - you still can create another table of shipping order address, that is 1 to 1 if you want, I thought this example suited more for the mentioned feature. A lot of people here didn't get the actual value of the feature. I worked on a Ecommerce aggregator project, so these were a few of the many requirements.
@jeroen7362
@jeroen7362 Жыл бұрын
@@MikyShooter Yes we are on the same page, the profile address is not referenced by the order. (also not via customer). The order address should be on the order and should not be updated or used outside the fullfilling of that one order. The customer has a profile with an up to date address on it. That is on a separate table (you could have 2 addresses for a customer, one is shipping default and the other is invoice) You should not need any orders table to find the latest address for a customer when he gets on the checkout page. A customer without any orders can have an address.
@gianlucalocri
@gianlucalocri Жыл бұрын
Finally!!! 🤩 Thanks Milan!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Sure thing :)
@tonystoynev7969
@tonystoynev7969 Жыл бұрын
Hey, another great video! But I am not getting the point of having a collection of complex types inside the entity? How this collection will be mapped into the database?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Could be all mapped to one column as JSON
@ArcaneEye
@ArcaneEye 9 ай бұрын
​@@MilanJovanovicTechcan't you already do that with hasconversion? And wouldn't it be faster to query a relational table than having the SQL server do string magic to find your query target?
@aerostorm_
@aerostorm_ 6 ай бұрын
​@@ArcaneEye to answer your somewhat older question, this is essentially a built-in HasConversion json implementation. Document databases are supported by EF now and this paradigm makes more sense if you are using EF to abstract a document DB. If you are abstracting a SQL DB then this feature is not as optimal as querying with relations.
@antonmartyniuk
@antonmartyniuk Жыл бұрын
I like this feature much, hope collections will be supported too until EF 8 release
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I don't think we get that in EF 8 :/
@silvertek
@silvertek Жыл бұрын
Will this avoid the exception when using stringly typed ids since we use them as both value/nonentity types for the aggregate but as entity types when we reference them from another aggregate?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Give it a try? 😁
@matthewrossee
@matthewrossee Жыл бұрын
You mean the identity paradox presented by Amichai Mantinband on his channel? I'm curious as well. Have you tried it yet?
@vinr
@vinr Ай бұрын
Can all properties of the complex type be nullable, I don't think it is possible
@MilanJovanovicTech
@MilanJovanovicTech Ай бұрын
Doesn't seem like it: github.com/dotnet/efcore/issues/31376
@xiovaii
@xiovaii Жыл бұрын
Finally!
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@astralpowers
@astralpowers Жыл бұрын
Collections for value objects would really be useful for my use case
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
We'll see if it makes the cut
@ArcaneEye
@ArcaneEye 9 ай бұрын
How? I'm really curious as I can't see a situation where that would be the correct approach.
@vallJune
@vallJune 4 ай бұрын
Hi Milan.First of all many thanks. Would you happen to know how to configure ComplexObject as an optional? Book { Author? Author}
@MilanJovanovicTech
@MilanJovanovicTech 4 ай бұрын
Not supported right now
@vallJune
@vallJune 4 ай бұрын
@@MilanJovanovicTech thank you, Milan. The OwnsOne seems to work for me
@Sander-Brilman
@Sander-Brilman Жыл бұрын
how would collections work with complex types? shouldnt a new table be added for that since not all db providers support the array type
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Or JSON into one column?
@rusektor
@rusektor Жыл бұрын
Doesn't this remind [ComplextType] attribute in EF 4.0?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yes, these are old EF features ported to EF Core
@JordiC354
@JordiC354 8 ай бұрын
Hi Milan, do you achieve that complex property works with typed ID, like BookId(Guid ID)?
@MilanJovanovicTech
@MilanJovanovicTech 8 ай бұрын
Does it not work for you?
@JordiC354
@JordiC354 8 ай бұрын
@@MilanJovanovicTech Not for primary key. Does it work for you?
@gorgestv6340
@gorgestv6340 Жыл бұрын
I don't understand what is the meaning of the Owned types
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Read the docs: learn.microsoft.com/en-us/ef/core/modeling/owned-entities
@jeroen7362
@jeroen7362 Жыл бұрын
I do not see the point. what does this solve? Why not have two real classes and tables? In real life an author writes 1 or more books. Why would you store the author multiple times? My advise is to not use any magic in EF core. Also implicit many2many tables that can be created by EF. Just write your own many2many class, you can then for instance put the timestamp and userid on it, who added that connection. Your are then in full control of everything.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You're missing the forest for the trees. This is about EF 8 Complex types. Not "correct" data modeling.
@jeroen7362
@jeroen7362 Жыл бұрын
@@MilanJovanovicTech Yes so why am i missing the forest? I can not think of any "complex type" scenario that i would put in a database like that. Your sample with books and author sure isnt it so what real life thing would you ever put in a database like that? Only problems need a solution, i have never encountered a problem in over 20 years of software development and database design that this would solve. Edit: the order with shipping addres as mentioned here could be a scenario. Still i would not use it for that. Just add a few fields for the address, postal code and town, country and done. probably country would be a foreign key to the country table.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@jeroen7362 See, there are scenarios where this is practical. You'd use an anemic model with properties for the address. Someone else prefers having a type.
@phugia963
@phugia963 Жыл бұрын
finally we can have a good EF features to support define & map value object to the database 😄
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Yes!
@EzequielRegaldo
@EzequielRegaldo Жыл бұрын
Its AWESOME ! thank you so much for your content
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Glad you enjoy it!
@vasiliylu8054
@vasiliylu8054 Жыл бұрын
Thanks! It's very cool feature
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You're welcome :)
@kennyhendricks4293
@kennyhendricks4293 Жыл бұрын
I am glad that this has been fixed
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
We're getting there :)
@nasermasri9954
@nasermasri9954 Жыл бұрын
First!😅
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Blazing speed!
@greensporevalley
@greensporevalley Жыл бұрын
.NET stare
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
👀
@techpc5453
@techpc5453 Жыл бұрын
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
👋
@ArcaneEye
@ArcaneEye 9 ай бұрын
Quick question re: list of complex types. If a complex type is mapped to columns in a table alongside the entity they belong to, how would you map a list of those to the table? Isn't that exactly what navigation properties are for?
@MilanJovanovicTech
@MilanJovanovicTech 9 ай бұрын
Lists not supported yet
@joebyrne7343
@joebyrne7343 Жыл бұрын
Must the columns be author_? Can this be implemented in db first scenario where the existing columns may not follow that naming convention?
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
You, configure with ComplexProperty and define column with HasColumnName("your_existing_db_col")
@MaxwellGomesdeMorais
@MaxwellGomesdeMorais Жыл бұрын
awesome
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Thanks a lot!
@kis.stupid
@kis.stupid Жыл бұрын
I believe you but I don't understand why that errored before? Because of the reference? It has no PK. I did notice seeding those owned types needed to be initialized as anonymous types. I think you could use Records as well, that brings along other complications ofc. I would like to learn more about those "nvarchar(max)", how to globally limit that, if you should limit that. Or how optimized that is by default.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It does have a "PK" as far as EF is concerned. Give it a try with Owned types and you'll see.
@nick_stelmakh
@nick_stelmakh Жыл бұрын
the poor example. didn’t show all wide spectrum of this update
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
Now you have what to show us in your video
@nick_stelmakh
@nick_stelmakh Жыл бұрын
i like your videos but to be honest it so not this time, you could have spent more time giving end watchers a real example of why and for what it appeared@@MilanJovanovicTech
@nicolasL009
@nicolasL009 Жыл бұрын
Very informative video! Too bad it'll take a while before I get to use EFCore 8 at my current job. Stubbled upon the issues mentioned in the video quite a few times with older EF versions. Keep up the good work :)
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
I think EF 8 will work on olders .NET versions, need to check though 🤔
@modernkennnern
@modernkennnern Жыл бұрын
@@MilanJovanovicTech I think they try to keep it working on the latest LTS. In this case, that is .Net 8. But I might be wrong - it might still work on .Net 6. I know that EF7 only works on 6+
@kodindoyannick5328
@kodindoyannick5328 5 ай бұрын
Thanks Milan
@MilanJovanovicTech
@MilanJovanovicTech 5 ай бұрын
Any time
@KevinBecker-p4u
@KevinBecker-p4u Жыл бұрын
This is a very poor example of a Value Object. I think the feature might be useful in some scenarios, but this example is not one. It would be nice to see a real-world example instead.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
The point is EF Complex types and how they can be used to map Value objects. This is far better than Owned types that we had thus far. And if I put too much effort into the example, it moves focus away from what I wanted to showcase here. Can't satisfy everyone
@AndersBaumann
@AndersBaumann Жыл бұрын
Yes. Author is definitely not a value object. Use money, address or email as examples.
@KevinBecker-p4u
@KevinBecker-p4u Жыл бұрын
@@MilanJovanovicTech This is the problem I run into when learning new techniques, finding bad examples and not understanding why I would want to do such a thing. I don’t use value types and your example didn’t make me understand any better as I was wondering why anyone would want to “flatten” data in a relational situation.
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
@@KevinBecker-p4u Funny thing is, the people who already knew about Value objects didn't think this was a bad example. And they were my target audience with this video. I didn't want to focus at all on "why" you should use a Value object. This was simply about "how" to use EF 8 Complex types to implement Value objects (and I'm kind of assuming you already know what they are, and how they fit into DDD)
@Dpaz2009
@Dpaz2009 10 ай бұрын
@user-rd4cd9zj1s People who say this is a poor example should create a tutorial showing us better or else even better shut up and thank for sharing. 😅
@wmalgoire
@wmalgoire Жыл бұрын
I feel bad for people getting obsessed by the business domain trivial example and not trying to understand this new feature.. Maybe you should post a video on active listening Milan 😂😂 I mean, there are other great contents on value objects use cases and benefits. Having struggled with poor implementations and complexity of value object persistence in efcore, I'm quite excited by this new feature! Even if in the meantime we'll have to handle collections manually..but that's a good step forward and I'll use this for sure 😊 All in all, another handy feature to keep in our toolbelt 👍 Thanks for your hard work Milan 🙏
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
It doesn't matter, I'm glad people are getting value from this and understanding the Complex Types feature 😁
@wmalgoire
@wmalgoire Жыл бұрын
@MilanJovanovicTech Right! What matters is communicating, not trying to change people opinions 😊 And if at least one people get value, that's a win 👍
@damiannizio4039
@damiannizio4039 Жыл бұрын
Couldn't you just have simply used conversion before? IE: builder.Property(x => x.SomeProperty).HasConversion(x => x.Value, x => new ValueObject(x));
@MilanJovanovicTech
@MilanJovanovicTech Жыл бұрын
How does that work for an object instead of a value?
@damiannizio4039
@damiannizio4039 Жыл бұрын
@@MilanJovanovicTech it simply creates a column and translates the VO into primitive of value type inside value object. When the data is retrieved from database it creates a new ValueObject.
@damiannizio4039
@damiannizio4039 Жыл бұрын
@@MilanJovanovicTech I hope that's what You meant
@svorskemattias
@svorskemattias Жыл бұрын
Yes that worked for single-valued value-objects! I use it all the time
@ArcaneEye
@ArcaneEye 9 ай бұрын
​@@svorskemattiasif you don't mind me asking, I'm having some issues doing linq .Where() queries relating to these single property value types. How do you go about that?
Mapping Domain-Driven Design Concepts To The Database With EF Core
18:06
Milan Jovanović
Рет қаралды 51 М.
Using Multiple EF Core DbContexts in a Single Application
17:46
Milan Jovanović
Рет қаралды 35 М.
💩Поу и Поулина ☠️МОЧАТ 😖Хмурых Тварей?!
00:34
Ной Анимация
Рет қаралды 2 МЛН
Please Help This Poor Boy 🙏
00:40
Alan Chikin Chow
Рет қаралды 20 МЛН
Minecraft Creeper Family is back! #minecraft #funny #memes
00:26
Making Entity Framework Core As Fast As Dapper
13:17
Nick Chapsas
Рет қаралды 87 М.
how Google writes gorgeous C++
7:40
Low Level
Рет қаралды 888 М.
100K Subscribers Special: My Journey, Career Advice, Future of .NET
16:36
RECORD TYPES | Exploring C# and DOTNET | Rahul Nath
15:32
Rahul Nath
Рет қаралды 3,4 М.
Working With Database Transactions In EF Core
14:11
Milan Jovanović
Рет қаралды 21 М.
Leaking Value Objects from your Domain
6:57
CodeOpinion
Рет қаралды 15 М.
The Identity Paradox | DDD, EF Core & Strongly Typed IDs
16:15
Amichai Mantinband
Рет қаралды 29 М.
💩Поу и Поулина ☠️МОЧАТ 😖Хмурых Тварей?!
00:34
Ной Анимация
Рет қаралды 2 МЛН