我有一个关于. asnotracking()扩展的问题,因为这都是相当新的和相当令人困惑的。

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

我的许多实体没有改变,所以不需要跟踪,但我有以下场景,我不确定什么将进入数据库,甚至在这种情况下它是否有区别。

以下是我目前正在做的事情:

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

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

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

步骤1和步骤2使用相同的上下文,但发生在不同的时间。我弄不明白的是是否有什么不同。由于第2步是一个更新,我猜无论如何都将击中数据库两次。

有人能告诉我有什么不同吗?


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


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

引用:

当使用实体框架和LINQ查询大型数据集时,如何避免内存溢出 实体框架大数据集,内存不足例外


实体框架和AsNoTracking

AsNoTracking做什么

实体框架提供了许多性能调优选项,以帮助您优化应用程序的性能。其中一个调优选项是. asnotracking()。这种优化允许你告诉实体框架不跟踪查询的结果。这意味着实体框架不会对查询返回的实体执行额外的处理或存储。然而,这也意味着您不能在不将这些实体重新附加到跟踪图的情况下更新它们。

使用AsNoTracking可以显著提高性能


没有跟踪LINQ到实体查询

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

优点 改进了常规LINQ查询的性能。 完全物化的物体。 用内置在编程中的语法编写是最简单的 语言。 缺点 不适合CUD操作。 某些技术限制,例如:使用DefaultIfEmpty的模式 OUTER JOIN查询的结果比简单的OUTER查询更复杂 实体SQL中的JOIN语句。 您仍然不能对一般模式匹配使用LIKE。

更多信息可在这里:

实体框架的性能考虑

实体框架和NoTracking


如果你有其他的东西改变DB(说另一个进程),需要确保你看到这些变化,使用AsNoTracking(),否则EF可能会给你的最后一个副本,你的上下文代替,因此它是好的通常使用一个新的上下文每次查询:

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


AsNoTracking()允许EF中的“每条记录的唯一键”需求被绕过(其他答案没有明确提到)。

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

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