.AsNoTracking() 有啥区别?

Posted

技术标签:

【中文标题】.AsNoTracking() 有啥区别?【英文标题】:What difference does .AsNoTracking() make?.AsNoTracking() 有什么区别? 【发布时间】:2012-08-31 08:35:23 【问题描述】:

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

谁能告诉我有什么区别?

【问题讨论】:

【参考方案1】:

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

【讨论】:

我们能否在select查询中为匿名类获得同样的好处,例如context.Users.Select(u=> new Name = u.Name )?谢谢。 @DilhanJayathilake:匿名类不代表实体本身,因此它们没有跟踪功能。 由于 EF6 有时会错误地推断视图上的实体键,AsNoTracking() 是否会忽略该键,因此可以替代手动修复该键(假设不需要该键的其他好处)。 另外注意,AsNoTracking最大的作用就是懒加载不起作用【参考方案2】:

查看此页面Entity Framework and AsNoTracking

AsNoTracking 的作用

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

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

【讨论】:

似乎收益有时会被抵消:***.com/questions/9259480/… 我通过一个复杂的查询加载父子关系并一步包含的性能提升大约 50%【参考方案3】:

不跟踪 LINQ to Entities 查询

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

优点

    提高了常规 LINQ 查询的性能。 完全实体化的对象。 使用程序内置的语法编写最简单 语言。

缺点

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

更多信息在这里:

Performance considerations for Entity Framework

Entity Framework and NoTracking

【讨论】:

“你仍然不能将 LIKE 与一般模式匹配一​​起使用” - 我找不到任何官方参考,它对我来说似乎工作正常【参考方案4】:

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

参考资料:

How to avoid memory overflow when querying large datasets with Entity Framework and LINQ Entity framework large data set, out of memory exception

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

重申这一点对视图的重要性,我有一个来自视图的查询,该查询在通过 SSMS 运行时返回 7 条唯一记录。当通过 EF 运行时,没有 AsNoTracking 修饰符,我得到第一条记录,第二条的三个副本和第三个的三个副本。这花了很多令人难以置信的头来修复,它使用了 AsNoTracking 来修复它! 我在使用 Linq to Entities 查询没有主键的视图时遇到了同样的问题。经过半天的挠头才发现AsNoTracking。这个 ASP.Net 论坛帖子最终将我引向了它。 forums.asp.net/t/…【参考方案6】:

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

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

【讨论】:

以上是关于.AsNoTracking() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

AsNoTracking()非跟踪数据 查询

WebSVN 有啥好的替代品吗? [关闭]

关键词汇理解与用法

Linux(Ubuntu)。 SVN + TRAC。在 TRAC 中显示 SVN 项目

trac

带有 Subversion 的 Trac 缺少“浏览源代码”按钮