在AsNoTracking()后面是否有任何隐藏的功能?

本文关键字:隐藏 任何 功能 是否 AsNoTracking | 更新日期: 2023-09-27 18:16:50

我正在处理一个大项目(有许多不同的厨师在做汤,多年过去了),刚刚发现了下面的代码。

private IEnumerable<string> SomeSome()
{
  using(DataModel context = DataModel())
  {
    context.SomeEntityName.AsNoTracking();
    ...
    return context.SomeEntityName
      .Where(entity => true)
      .Select(entity => String.Empty);
  }
}

现在,我已经三次检查了AsNoTracking方法,它清楚地说返回一个可查询的对象,它与EF的跟踪设施没有业务关系。可以说,这是ORM的一种"即发即忘"。

注意:

  1. 我们不存储值,也不处理返回值
  2. 的内容
  3. 我们获得一组新的(显然是可跟踪的)对象来处理

我想删除这一行。然而,作为一个谦虚的人(例如,不怕破坏系统),我在删除任何东西之前都很谨慎。在我的上下文中是否存在可能影响实体的第二次检索的隐式更改?

我没有找到任何关于它的信息——既不支持也不反对这个理论。此外,我还没有找到任何其他版本的EF 5.0的文档(如上面的链接所示),但我们正在使用EF 6.1.3,我知道问题的方法在EF 4中也存在。

在AsNoTracking()后面是否有任何隐藏的功能?

如果这行代码与您的项目完全相同,那么就没有更改。

context.SomeEntityName.AsNoTracking();

this ^^^返回未保存在任何地方的可查询对象。如果您删除了这一行,那么下面的查询将不会有什么不同。

乌利希期刊指南我已经看了EF的源代码。据我所知,AsNoTracking()不会改变DbContext对象的状态。因此,如果在一个查询上调用该方法,它应该不会影响其他查询的执行。如果是这样,这是EF的一个bug,应该报告。在我的项目的多个地方,我有相同的dbContext查询跟踪和没有。一切都如预期般顺利。

来源:

  • DbQuery.AsNoTracking ()
  • DbHelpers。CreateNoTrackingQuery
  • TranslatorVisitor.Visit() Line 341+

如果序列化这个对象,那么如果定义了多对多关系,可能会遇到问题。AsNoTracking()调用可能已经到位,以解决这个问题,如下所示:

具有一对多关系的实体框架对象序列化

平心而论,这是一个hack,可能导致(正如你刚刚注意到的)人们想知道为什么在维护时调用这个。如果这是序列化的,最好有一个单独的可序列化的DTO,而不是传递上下文对象本身。


我还注意到,已经有一些关于关闭跟踪以提高性能的讨论。根据您的目标,禁用跟踪可以(显然)显著提高性能。