DbSet <T> .Attach()方法是否将已修改的属性标记为“已修改”?

时间:2019-08-13 03:02:01

标签: c# entity-framework-core

假设我们有一个Person类(具有Id和Age的属性),假设我们需要将ID为1的人的Age从29更改为30,

Person p = new Person(){ Id = 1 }  //Age is default to 0 here, but does't matter, because it is going to be changed later
var entity = context.Persons.Attach(p);
p.Age = 30;

Console.WriteLine("entity state:" + entity.State);
foreach (var modifiedProperty in entity.Properties.Where(p => p.IsModified))
{
   Console.Write($"The {modifiedProperty.Metadata.Name} property is marked as modified");
}
context.SaveChanges();

,输出显示:

entity.State未更改,并且未将任何属性标记为已修改,但是EF内核仍然生成了一个更新SQL来设置[年龄] = 30, '很困惑,如果实体状态保持不变并且EF核心认为没有属性修改,那么EF核心不应该生成更新SQL吗?

如果我使用Update()方法而不是Attach()

...
var entity = context.Persons.Update(p);
...

然后一切正常,实体状态已修改,年龄被标识为已修改属性?

1 个答案:

答案 0 :(得分:2)

调用context.ChangeTracker.DetectChanges()时,实体的状态不会立即更新,而是会重新计算。

属性context.ChangeTracker.AutoDetectChangesEnabled默认设置为true。这意味着在调用context.SaveChanges()时,将首先自动调用context.ChangeTracker.DetectChanges(),然后更新实体的状态。

根据文档https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbset-1.update?view=efcore-2.1,实体对象的所有属性都将由update方法本身以Modified状态标记,无论该属性值是否被真正修改。因此,Update方法不是使用检测EF的更改功能,而是强行设置实体的状态。