实体框架代码首先更新复杂类型的单个属性

本文关键字:类型 单个 属性 复杂 更新 框架 代码 实体 | 更新日期: 2023-09-27 18:09:34

我有一个奇怪的行为。我想更新一个复杂类型的单个属性。当我用IsModified指定要更新的属性时(有些属性为真,有些为假),我没有更新任何内容。如果我没有指定复杂类型的属性,则更新复杂属性的每个字段。

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();

这产生:

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

如果我不指定SubProperty2的IsModified为false,我在SQL分析器中有以下内容:

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

为什么我指定了"IsModified"在一些没有更新的属性上?

编辑

经过几次尝试,我可以确认,如果我检查这两行,当一个复杂类型的一个属性被设置为IsModified为False时,整个复杂类型没有更新。

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

如果我将任何属性设置为True,没有问题,但当1个属性设置为false (IsModified)时,整个子属性不在namesOfChangedProperties变量中。

编辑2

我尝试使用ComplexProperty与相同的结果。

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();

实体框架代码首先更新复杂类型的单个属性

这是EF对复杂类型的更改跟踪方式的限制。EF不跟踪属性级别的更改,而只跟踪整个对象是否被修改。这是作为EF1的一部分内置的限制,并且没有被移除。一方面,对于那些想要更细粒度的更改跟踪的人来说,消除这个限制是很好的。然而,另一方面,将复杂对象视为不可变的"值类型"通常被认为是最佳实践。对于这样的值类型,总是设置整个对象,这使得更细粒度的更改跟踪不太有用。此外,更细粒度的变更跟踪并不是一个经常被要求的特性,所以EF团队不太可能很快就会着手这项工作。