自动检测更改

使用大多数 POCO 实体时,确定实体如何更改(因此需要将哪些更新发送到数据库)由检测更改算法进行处理。 检测更改的工作原理是检测实体的当前属性值与原始属性值之间的差异,原始属性值在查询或附加实体时存储在快照中。 本主题所介绍的方法同样适用于查询使用 Code First 和 EF 设计器创建的模型。

默认情况下,在调用以下方法时实体框架自动执行检测更改:

  • DbSet.Find
  • DbSet.Local
  • DbSet.Add
  • DbSet.AddRange
  • DbSet.Remove
  • DbSet.RemoveRange
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

禁用自动检测更改

如果跟踪上下文中的大量实体,并且在循环中多次调用其中某个方法,则可关闭在循环期间的更改检测来获得显著的性能改进。 例如:

using (var context = new BloggingContext())
{
    try
    {
        context.Configuration.AutoDetectChangesEnabled = false;

        // Make many calls in a loop
        foreach (var blog in aLotOfBlogs)
        {
            context.Blogs.Add(blog);
        }
    }
    finally
    {
        context.Configuration.AutoDetectChangesEnabled = true;
    }
}

不要忘记在循环后重新启用更改检测 - 我们使用了 try/finally 来确保始终重新启用更改,即使循环中的代码引发异常。

禁用和重新启用的替代方法是,使自动检测更改一直保持关闭状态,并且显式调用context.ChangeTracker.DetectChanges或努力使用更改跟踪代理。 这两个都是高级选项,可以轻松地在应用程序中引入细微 bug,因此请谨慎使用它们。

如果需要在上下文中添加或删除多个对象,请考虑使用 DbSet.AddRange 和 DbSet.RemoveRange。 此方法仅在添加或删除操作完成后自动检测更改一次。