Question

I am having a weird behavior. I want to update a single property of a complex type. When I specify properties to be updated with IsModified (some property are to true and some to false) I have nothing updated. If I specify no property of the complex type, every field of the complex property are updated.

public class MyEntity
{
    public MyComplexClass Property1 { get; set; }
}

//... The code below doesn't work, in fact it update nothing
var entityLocal = this.Set<MyEntity>().Local.SingleOrDefault(d => d.Id == entity.Id);
if (entityLocal == null)
{
   entityLocal = this.Set<MyEntity>().Attach(entity);
}
this.ChangeTracker.Entries<MyEntity>().Single(d => d.Entity == entityLocal).State = EntityState.Modified;
this.Entry(entity).Property(s => s.Property1.SubProperty1).IsModified = true;
this.Entry(entity).Property(s => s.Property1.SubProperty2).IsModified = false;//This seam to remove all update of the complex type...?
this.SaveChanges();

This produce :

update [dbo].[MyEntity]
set @p = 0
where (([Id] = @0))

If I do not specify the IsModified to false of the SubProperty2, I have the following in the SQL profiler:

update [dbo].[MyEntity]
set [Property1_SubProperty1] = @0, [Property1_SubProperty2] = null
where (([Id] = @1))

How come when I specify "IsModified" on some property that nothing is updated?

Edit

After several try, I can confirm that if I check with those two lines that it's when 1 property of a complex type is set to IsModified to False that the whole complex type is no updated.

var entry = DatabaseContext.Entry(entity);
var namesOfChangedProperties = entry.CurrentValues.PropertyNames.Where(p => entry.Property(p).IsModified).ToArray();

If I set to True any property, no problem but when 1 property is set to false (IsModified), the whole SubProperty is not inside the namesOfChangedProperties variable.

Edit 2

I have try to use ComplexProperty with the same result.

this.ChangeTracker.Entries<MyEntity>().Single(d => d.Entity == entityLocal).State = EntityState.Modified;
this.Entry(entity).ComplexProperty(s => s.Property1).Property(d => d.SubProperty1).IsModified = true;
this.Entry(entity).ComplexProperty(s => s.Property1).Property(d => d.SubProperty2).IsModified = false;
this.SaveChanges();
Was it helpful?

Solution

This is a limitation of the way EF does change tracking of complex types. EF doesn't track changes at the property level, but rather only tracks that the whole object is modified or not. This is a limitation that was built in as part of EF1 and has not been removed. On the one hand it would be good to remove this limitation for those people who do want more granular change tracking. However, on the other hand it is often considered best practice to treat complex objects as immutable "value types". For such value types the whole object is always set, which makes more granular change tracking less useful. Also, more granular change tracking is not a very commonly requested feature so it is unlikely that the EF team would work on it soon.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top