【问题标题】:DbSet<T>.Attach() method does't mark modified properties as "modified"?DbSet<T>.Attach() 方法不会将修改后的属性标记为“已修改”?
【发布时间】:2019-08-13 03:02:01
【问题描述】:

假设我们有一个 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 来设置 [Age] = 30,我是困惑,如果实体状态不变,EF核心认为没有属性修改,那么EF核心不应该生成Update SQL吗?

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

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

那么一切正常,Entity状态被修改,Age被标识为修改属性?

【问题讨论】:

  • myContext.ChangeTracker.DetectChanges();
  • @JohnB 我更新了我的帖子。那么为什么使用 Update() 方法可以识别修改的属性而 Attach() 不能呢?

标签: c# entity-framework-core


【解决方案1】:

实体的状态不会立即更新,而是会在调用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的变化检测功能,而是强制设置实体的状态。

【讨论】:

  • 那么为什么如果我使用 Attach() 方法,EF 无法识别修改的属性,但如果我使用 Update() 方法,那么 EF 可以识别修改的属性?
猜你喜欢
  • 1970-01-01
  • 2010-12-02
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多