You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not sure if this is an issue with the library or EF Core itself, but it may be worth being aware of at least.
If you use HasJsonConversion()on a property of an owned type and you replace the owned type (e.g. because you're using immutable value objects, so you cannot modify the properties directly), the Json property is always recognized as a change even if its property value is the same as the original so the field is always included in an update to the database (I'm using SQL Server for storage).
Extremely basic example:
publicclassApplicationDbContext:DbContext{publicApplicationDbContext(DbContextOptions<ApplicationDbContext>options):base(options){}protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.Entity<Entity>().Property(e =>e.Items).HasJsonValueConversion();modelBuilder.Entity<Entity>().OwnsOne(e =>e.Owned, b =>{b.Property(o =>o.Items).HasJsonValueConversion();});}publicDbSet<Entity>Entities{get;set;}}publicclassEntity{publicintId{get;set;}publicstringField{get;set;}publicList<string>Items{get;set;}publicOwnedOwned{get;set;}}publicclassOwned{publicstringField{get;set;}publicList<string>Items{get;set;}}
Assume you already have an entity saved in the database that is equivalent to:
On the root entity itself, everything works as expected when assigning an equivalent value to the property:
// not sent as update, db value is the sameentity.Items=newList<string>(){"Hello","World!"};
On the owned entity, if you reassign the property without replacing the owned object itself, again everything works as expected:
// not sent as update, db value is the sameentity.Owned.Items=newList<string>(){"Homer","Simpson"};
If you replace the owned entity, then the value is always considered to be modified, even though regular values (string Field) are correctly handled:
entity.Owned=newOwned{// not sent as update even though owned entity is replaced, db value is the sameField="string",// SENT AS UPDATE, db value is sameItems=newList<string>(){"Homer","Simpson"};}
Even if you reassign the value to the exact same reference, it's still treated as modified:
varowned=entity.Owned;entity.Owned=newOwned{// not sent as update even though owned entity is replaced, db value is the sameField=owned.Field,// SENT AS UPDATE, db value is sameItems=owned.Items}
It's almost like the change tracker is not taking into consideration the ValueComparer when fixing up the owned object's properties after a reassignment. Do you think there is anything the library could do to help here?
If I could find out which properties use the JsonValueComparer/JsonValueConverter while looping through ChangeTracker.Entries I could probably fix up the properties, but I don't know how to find out if a property has a ValueConverter/ValueComparer with the metadata that is available at that point. Finding the properties with a JasonValueComparer is easy enough, but the properties are not marked as modified, so I'm not sure why they are still flowing to the database update.
The text was updated successfully, but these errors were encountered:
Interesting. I've experienced a lot of weird activity around the EF Core owned types and their tracking, and have tried to avoid using them altogether so far. Are you able to repro this on inmemory unit test?
The owned types are indeed proving to be challenging. InMemory is hard to tell. I'm not aware of anything equivalent to a SQL statement that shows how the objects are being persisted to the in-memory database.
The pointless update call is probably not even a big deal for most cases. But it could cause false positives for update triggers or, in my case, logic that is intended to fire if any properties are modified. I think I might be able to work around that, but the original issue is still an oddity. There are other unrelated issues with nested owned types so maybe they just aren't quite ready for prime time.
I guess there's not really any action you can take on your end, other than just being aware of potential issues with owned types. I don't think the the converter or comparer are the source of this, given that everything works as expected on the root entity.
I'm not sure if this is an issue with the library or EF Core itself, but it may be worth being aware of at least.
If you use
HasJsonConversion()
on a property of an owned type and you replace the owned type (e.g. because you're using immutable value objects, so you cannot modify the properties directly), the Json property is always recognized as a change even if its property value is the same as the original so the field is always included in an update to the database (I'm using SQL Server for storage).Extremely basic example:
Assume you already have an entity saved in the database that is equivalent to:
On the root entity itself, everything works as expected when assigning an equivalent value to the property:
On the owned entity, if you reassign the property without replacing the owned object itself, again everything works as expected:
If you replace the owned entity, then the value is always considered to be modified, even though regular values (string Field) are correctly handled:
Even if you reassign the value to the exact same reference, it's still treated as modified:
It's almost like the change tracker is not taking into consideration the
ValueComparer
when fixing up the owned object's properties after a reassignment. Do you think there is anything the library could do to help here?If I could find out which properties use theFinding the properties with aJsonValueComparer
/JsonValueConverter
while looping throughChangeTracker.Entries
I could probably fix up the properties, but I don't know how to find out if a property has aValueConverter
/ValueComparer
with the metadata that is available at that point.JasonValueComparer
is easy enough, but the properties are not marked as modified, so I'm not sure why they are still flowing to the database update.The text was updated successfully, but these errors were encountered: