Entity framework 实体框架mergeoption不跟踪不良性能

Entity framework 实体框架mergeoption不跟踪不良性能,entity-framework,entity-framework-4,linq-to-entities,Entity Framework,Entity Framework 4,Linq To Entities,我有一个奇怪的行为,试图执行一个将ObjectQuery MergeOption声明为“NoTracking”的查询,在这种情况下,实体框架不应该附加任何实体,也不应该创建相对ObjectStateEntry来跟踪实体状态 问题在于,使用默认的mergeoption(即AppendingOnly)时,相同的查询只需要10秒,如果我尝试指定notracking,则需要1分钟以上的时间,而不是提高性能 有人对此有解释吗?如果通过设置NoTrackingmerge选项禁用更改跟踪,则可以节省将对象附加

我有一个奇怪的行为,试图执行一个将ObjectQuery MergeOption声明为“NoTracking”的查询,在这种情况下,实体框架不应该附加任何实体,也不应该创建相对ObjectStateEntry来跟踪实体状态

问题在于,使用默认的mergeoption(即AppendingOnly)时,相同的查询只需要10秒,如果我尝试指定notracking,则需要1分钟以上的时间,而不是提高性能


有人对此有解释吗?

如果通过设置
NoTracking
merge选项禁用更改跟踪,则可以节省将对象附加到上下文的性能成本,但另一方面也会丢失身份管理

这意味着可能会有更多的对象——许多具有相同密钥的对象——被物化

示例:假设您有一个
用户
实体,其导航属性为
角色
集合。另外,假设数据库中有100万用户,并且所有用户都处于相同的10个角色中,即每个用户都有一个包含10个元素的角色集合。如果运行以下查询

var users = context.Users.Include("Roles").ToList();
…具体化和实例化对象的数量取决于合并选项:

  • 如果不使用
    NoTracking
    ,内存中将有1.000.010个对象,即100万个用户,但只有10个角色,因为标识映射将确保每个键只具体化一个角色并附加到上下文。相同的10个角色实例用于所有用户的
    角色
    集合

  • 但是,如果使用
    NoTracking
    ,EF将不会将对象附加到上下文,因此身份管理将被禁用,并且内存中将有11.000.000个对象:100万用户和每个用户10个角色实例,即1000万个角色对象。因此,您拥有的物化对象数量是将对象附加到上下文时的10倍多

对象物化分为:

操作:具体化对象
相对成本:适中
频率:查询返回的每个对象一次。

评论: 读取返回的DbDataReader对象并创建 对象并设置基于中的值的特性值 DbDataRecord类的每个实例如果对象已存在 在ObjectContext中,查询仅使用appendor 保留更改合并选项,此阶段不会影响性能。


换句话说:如果查询使用
NoTracking
merge选项,此阶段确实会影响性能,禁用的更改跟踪的性能优势可能会被禁用的身份管理和成倍的对象物化的缺点所破坏。

您是如何衡量查询执行的?基本上在使用ToList()但您执行查询多少次,以及您使用的执行顺序是什么?我执行了一次查询,但尝试了多次执行,执行速度明显加快,但“notracking”查询仍然比“appendingonly”查询慢。“执行顺序”是什么意思?只需比较两者的单个执行。如果您在单个应用程序运行中同时执行这两个命令,请尝试以相反的顺序执行它们。这是否仍然适用?说明:没有跟踪查询仍在执行查询中执行标识解析。如果结果集多次包含同一实体,则结果集中每次出现时都将返回同一实体类实例。但是,弱引用用于跟踪已返回的实体。如果具有相同标识的前一个结果超出范围,并且运行垃圾收集,则可能会得到一个新的实体实例。有关更多信息,请参阅查询的工作原理。它与EF Core 3.0再次相关。您的链接文档说明了此更改:“无跟踪查询[…]不进行标识解析。因此,即使结果中多次包含同一实体,也会返回实体的新实例。在EF Core 3.0之前的版本中,此行为有所不同。”