我有一个关于. 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步是一个更新,我猜无论如何都将击中数据库两次。

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


当前回答

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

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

其他回答

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

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

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

实体框架和AsNoTracking

AsNoTracking做什么

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

使用AsNoTracking可以显著提高性能

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

引用:

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

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

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

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