是否调用实体框架中的AsNoTracking是否重要?

use*_*107 17 c# asp.net-mvc performance entity-framework

在编写实体框架查询时,调用AsNoTracking方法的位置是否重要?例如

var matchingCustomers = context.Customers.AsNoTracking().Where(n => n.city == "Milan").Skip(50).Take(100).OrderBy(n => n.Name).ToList();
var matchingCustomers = context.Customers.Where(n => n.city == "Milan").AsNoTracking().Skip(50).Take(100).OrderBy(n => n.Name).ToList();
var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).AsNoTracking().Take(100).OrderBy(n => n.Name).ToList();
var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).Take(100).AsNoTracking().OrderBy(n => n.Name).ToList();
var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).Take(100).OrderBy(n => n.Name).AsNoTracking().ToList();
var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).Take(100).OrderBy(n => n.Name).ToList().AsNoTracking();
Run Code Online (Sandbox Code Playgroud)

我喜欢将它添加到语句的末尾但是在调用ToList之前这样:

var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).Take(100).OrderBy(n => n.Name).AsNoTracking().ToList();
Run Code Online (Sandbox Code Playgroud)

Ale*_*rck 19

不,没关系:( 来源)

应用了NoTracking的新查询,或者如果不支持NoTracking则查询源查询.

因此,您要么在开始时进行,要么使用方法链扩展"新"查询,要么在最后执行,然后获取"新"查询.只要在执行查询之前调用它就可以了.

  • @PanagiotisKanavos是的,这就是为什么我说"在执行查询之前".`ToList()`执行查询.我现在把它放在粗体中 (7认同)
  • 实际上它确实在最后一种情况下 - 在`ToList`之后调用`AsNoTracking`可能会抛出.如果没有,它实际上将是一个无操作,因为在调用'AsNoTracking`时实体已经在内存中 (3认同)

jlv*_*ero 6

我觉得

var matchingCustomers = context.Customers.Where(n => n.city == "Milan").Skip(50).Take(100).OrderBy(n => n.Name).ToList().AsNoTracking();
Run Code Online (Sandbox Code Playgroud)

很重要,因为一旦EF执行并追踪查询,你试图将NoTracking应用于已经在内存中的数据结构.

当您使用这个流畅的API; 您正在定义查询而不执行它,直到您执行查询为止.ToList()将执行查询并将数据带入内存以将其转换为List<T>数据结构.

让我们拆分命令来理解这个:

  • context.Customers - >从Customers中选择[*]
  • 哪里(n => n.city =="米兰") - >从城市=='米兰'的客户中选择[*]
  • 跳过(50).取(100) - >从客户中选择[*],其中城市=='米兰'OFFSET 50 ROWS FETCH NEXT 100 ROWS ONLY
  • 订单名称 - >从客户中选择[*],其中city =='Milan'OFFSET 50 ROWS FETCH NEXT 100 ROWS ONLY ORDER BY name
  • ToList() - >执行查询并默认将数据带入内存跟踪!
  • AsNoTraking() - >什么也没做,因为EF已经执行了查询并跟踪了数据.

  • 在回答问题之前,请先尝试做你要谈论的事情。您无法在 ToList 之后调用 AsNoTracking,因为您不再有 IQueryable 来调用它。它会给出编译时错误。 (2认同)
  • 物理上不可能编译并不是“什么都不做”。 (2认同)