获取具有AsNoTracking()的实体是否禁用对DetectChanges()的自动调用?

Say*_*Pal 25 entity-framework query-performance ef-code-first

我已经认识到这一概念AsNoTracking(),DetectChanges()以及AutoDetectChangesEnabled最近.据我所知,当使用Entity Framework从数据库中获取记录时AsNoTracking(),实体框架不会跟踪这些记录的任何更改,在这种情况下更新获取记录的任何属性都将失败.

我的问题是,如果以这种方式获取记录,它是否也会导致禁用对DetectChanges()的自动调用,或者是否必须通过设置显式完成:

Context.Configuration.AutoDetectChangesEnabled = false;
Run Code Online (Sandbox Code Playgroud)

另请告诉我,如果在为了只读的目的而严格获取数据时执行这两个操作,它会产生什么影响(在性能方面):

Context.Configuration.AutoDetectChangesEnabled = false;
Context.Set<T>().AsNoTracking();
Run Code Online (Sandbox Code Playgroud)

Ger*_*old 31

它还会导致禁用自动调用DetectChanges()

不,不会.但你必须意识到这一点AsNoTracking并且DetectChanges彼此无关(除了成为EF的一部分).AsNoTracking无论是否启用AutoDetectChanges,无论如何都将检测到的对象将永远不会被检测到.此外,AsNoTracking在一个DbSet层面上,AutoDetectChangesEnabled在上下文层面上工作.让DbSet方法影响整个上下文会很糟糕.

或者[设置AutoDetectChangesEnabled]必须明确地完成

好吧,你可能不应该禁用AutoDetectChanges.如果你这样做,你必须知道你做了什么.

如果两个动作都被执行,它会产生什么影响(在性能方面)

如上所述,它们并不相关.它们都可以以自己的方式提高性能.

  • AsNoTracking如果你想获取只读数据是很好的.它没有副作用(如:效果很明显)
  • 设置会AutoDetectChangesEnabled = false停止自动调用DetectChanges(可能很多),但它有副作用,需要注意.来自Lerman&Miller的书DbContext:

    需要调用DetectChanges时的工作并不像它可能出现的那样微不足道.实体框架团队强烈建议您在遇到性能问题时仅交换手动调用DetectChanges.还建议仅针对性能较差的代码段选择退出自动DetectChanges,并在有问题的部分完成执行后重新启用它.


Ter*_*tta 20

我们发现设置AutoDetectChangesEnabled = false可能会产生大量(即10倍)性能影响.

背景:我们的系统完全由使用变化检测代理的EF模型对象组成.也就是说,我们所有的DB字段和关系属性都被声明为虚拟.我们还有一个相对深度结构化的对象模型.那就是对象A包含一组对象B,它又包含一组对象C等.我们观察到通过EF/LINQ查询实例化这些对象的非平凡(> 100)是很昂贵的.例如,在一种情况下,实例化250个对象需要大约2秒.我们还观察到实例化相同的结构,但使用匿名对象需要大约25毫秒.最后,我们观察到,如果我们设置AutoDetectChangesEnabled = false,我们可以使用查询实例化EF模型对象并再次实现约25毫秒.

所以,至少对我们来说,通过设置它是错误的,可以获得巨大的收益.我们使用工作单元模式,并明确指出工作单元是否为只读.对于只读工作单元,设置AutoDetectChangesEnabled = false非常安全,因为永远不会有任何变化.实际上,我们在初始发布两年后将这一更改添加到我们的系统中(因此代码中有许多预先存在的工作单元),并且更改没有破坏任何内容,并且显着提高了性能.

我们还进行了实验,AsNoTracking()发现它基本上没有提高性能.据我了解,一个查询AsNoTracking()意味着对象不会被放入身份映射中,如果在上下文中多次引用该对象(例如在不同的查询中),这将迫使EF从磁盘重新获取该对象.所以有一些潜在的缺点AsNoTracking().

实施细节:

  • 我们有一个DBContext的子类,它为我们的工作单元提供了大量的基础结构
  • 我们的工作单元基本上是一个围绕环境的轻量级包装
  • 当分配工作单元时(通常在使用块中),它通过注入接收这些上下文之一(我们使用Castle/Windsor)
  • 在初始化期间,工作单元调用上下文中的方法,将AutoDetectChangesEnabled设置为false
  • 目前,我们做这一切的时候,因为我们总是使用变化检测代理和他们不需要AutoDetectChangesEnabled
  • 以前我们只针对"只读"工作单元执行此操作,因为如果在UoW中没有修改任何内容则无需检测更改(当我们分配工作单元时,我们明确指示它是否为只读)
  • -