【问题标题】:EF Code First: is good to call DetectChanges just before SaveChanges?EF Code First:在 SaveChanges 之前调用 DetectChanges 好吗?
【发布时间】:2013-03-11 15:26:52
【问题描述】:

我读过几篇关于实体框架的文章(article1article2),它多次调用 DetectChanges,这使得处理大量数据时速度非常慢。

例如,我可以在初始化上下文时禁用autoDetectChanges,并在调用.SaveChanges() 之前调用DetectChanges() 吗?

上下文会识别插入/更改/删除的实体吗?

var _dbContext = new ProjectContext();
_dbContext.Configuration.AutoDetectChangesEnabled = false;

// add/edit/delete entities

_dbContext.ChangeTracker.DetectChanges();
_dbContext.SaveChanges();

这种方法应该有效吗?或者它可能会产生隐藏的错误?

【问题讨论】:

  • 不是 100% 确定它是否在后台做任何奇怪的事情,但我一直在使用类似的方法,没有发现任何不良副作用

标签: entity-framework ef-code-first


【解决方案1】:

Arthur Vickers 定义了一个规则,当DetectChanges 不需要被调用时(甚至在SaveChanges 之前)in this blog post

不调用 EF 代码将使上下文处于以下状态 如果不需要调用 DetectChanges 则需要调用 之前。

关于 AddDelete 这些是“EF 代码”方法,因为您要么调用 AddDelete,要么将 context.Entry(entity).State 的状态设置为 @ 987654330@ 或Deleted。因此,如果您只是遍历一堆实体并添加或删除它们,那么您根本不需要调用 DetectChanges

关于编辑,我相信它更微妙一些。当您使用以下任一方式更新实体时...

context.Entry(entity).CurrentValues.SetValues(someObject);

...或使用DbContext...的属性API...

context.Entry(entity).Property(e => e.SomeProperty).CurrentValue = someValue;

...那么您也不需要DetectChanges(即使在SaveChanges 之前也不需要),因为这些又是对“EF 代码”的调用。

如果您只是更改实体的属性值,例如...

entity.SomeProperty = someValue;

...那么上面链接的第二条规则in the same blog post 适用:

任何时候非 EF 代码更改实体的任何属性值或 复杂对象,则可能需要调用 DetectChanges。

我认为你实际上只需要在SaveChanges 之前调用一次DetectChanges 如果你只是循环一些实体,将它们加载或附加到上下文并更改一些(标量和复数)属性值。

如果你做更复杂的事情(也许关系改变?或其他什么?)你的方法可能不再安全,因为

  1. AutoDetectChanges 不会以它现在的方式实现,并且如果在 SaveChanges 之前只需要一次,则在许多 EF 方法中调用它

  2. 再次提到in the same blog post

    如果代码对实体的属性进行更改 而不是仅仅调用 Add 或 Attach,然后,根据规则 2,DetectChanges 将需要被调用,至少作为 SaveChanges 的一部分并且可能 也在之前然后。

    (我的亮点)

不幸的是,我不知道在需要SaveChanges 之前调用DetectChanges 时会显示的代码示例。但是由于上面的第 1 点,我确信这样的例子是存在的。

【讨论】:

  • 那是一篇很棒的帖子,谢谢。但我有点不清楚(对此感到抱歉): 1. 为什么 EF 在实际保存到数据库之前只能调用 DetectChanges 时需要调用 DetectChanges 这么多次? 2. 我正在使用具有普通属性的POCO 对象(未标有virtual)。当我更改对象属性值时,EF 会静默调用 DetectChanges() 吗?
  • @RaraituL:至第 1 点:我不知道。这就是我最后一句话的意思。第 2 点:没有。DetectChanges 稍后在 SaveChanges 和一堆其他 EF 方法中调用,而不是在您分配属性值时调用。 DetectChanges 然后将当前属性值与原始值(在对象上下文中存储为“快照”)进行比较,如果值更改,则属性将被标记为已修改。它被称为“基于快照的更改跟踪”。
【解决方案2】:

DetectChanges 可以解决的主要问题之一是当我们有ManyToMany 关系和AutoDetectChanges=false 时在EF 中持久化数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多