281

我有一个关于.AsNoTracking()扩展的问题,因为这一切都很新而且很混乱。

我正在为网站使用每个请求的上下文。

我的很多实体都没有改变,所以不需要跟踪,但我有以下情况,我不确定数据库的内容,甚至在这种情况下是否会有所作为。

这个例子是我目前正在做的:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

这与上面相同,但从.AsNoTracking()步骤 1 中删除:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

步骤 1 和 2 使用相同的上下文,但发生在不同的时间。我无法解决的是是否有任何区别。由于第 2 步是一个更新,我猜无论如何都会两次访问数据库。

谁能告诉我有什么区别?

4

6 回答 6

228

不同之处在于,在第一种情况下,上下文不会跟踪检索到的用户,因此当您要将用户保存回数据库时,您必须附加它并正确设置用户状态,以便 EF 知道它应该更新现有用户而不是插入一个新的。在第二种情况下,如果您使用相同的上下文实例加载和保存用户,则不需要这样做,因为跟踪机制会为您处理。

于 2012-08-31T08:39:20.647 回答
205

看到这个页面实体框架和 AsNoTracking

AsNoTracking 做什么

Entity Framework 公开了许多性能调整选项来帮助您优化应用程序的性能。这些调整选项之一是.AsNoTracking(). 这种优化允许您告诉Entity Framework不要跟踪查询的结果。这意味着Entity Framework不对查询返回的实体执行额外的处理或存储。但是,这也意味着如果不将这些实体重新附加到跟踪图,就无法更新它们。

使用 AsNoTracking 可以获得显着的性能提升

于 2014-04-02T09:26:15.073 回答
62

不跟踪 LINQ to Entities 查询

当您的查询用于读取操作时,建议使用 AsNoTracking()。在这些情况下,您会取回实体,但它们不会被您的上下文跟踪。这确保了最小的内存使用和最佳性能

优点

  1. 提高了常规 LINQ 查询的性能。
  2. 完全物化的对象。
  3. 使用编程语言内置的语法编写最简单。

缺点

  1. 不适合 CUD 操作。
  2. 某些技术限制,例如: 将 DefaultIfEmpty 用于 OUTER JOIN 查询的模式会导致比 Entity SQL 中的简单 OUTER JOIN 语句更复杂的查询。
  3. 您仍然不能将 LIKE 与一般模式匹配一​​起使用。

此处提供更多信息:

实体框架的性能注意事项

实体框架和 NoTracking

于 2016-06-13T13:06:13.953 回答
40

禁用跟踪还会导致您的结果集流式传输到内存中。当您处理大量数据并且不需要一次性使用整个数据集时,这会更有效。

参考:

于 2013-12-07T02:03:01.257 回答
17

AsNoTracking() 允许绕过 EF 中的“每条记录唯一密钥”要求(其他答案未明确提及)。

这在读取不支持唯一键的视图时非常有用,因为可能某些字段可以为空,或者视图的性质在逻辑上不可索引。

对于这些情况,“key”可以设置为任何不可为空的列,但是 AsNoTracking() 必须与每个查询一起使用,否则将跳过记录(按键重复)。

于 2018-02-06T23:09:44.957 回答
11

如果您有其他更改数据库的内容(例如另一个进程)并且需要确保您看到这些更改,请使用AsNoTracking(),否则 EF 可能会为您提供您的上下文所拥有的最后一个副本,因此通常在每个查询中使用一个新的上下文是很好的:

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

于 2017-07-04T14:50:29.560 回答