实体框架合并提示表现不佳

MaR*_*Ruf 46 linq-to-entities entity-framework entity-framework-4

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

问题是,不是增加性能而是变得更糟,相同的查询在默认合并(即AppendingOnly)时需要10秒,如果我尝试指定notracking则需要1分钟

有人对此有解释吗?

Sla*_*uma 148

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

这意味着可能会有更多的对象 - 许多具有相同键的对象 - 将被实现.

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

var users = context.Users.Include("Roles").ToList();
Run Code Online (Sandbox Code Playgroud)

...物化和实例化对象的数量取决于合并选项:

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

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

对象实现归类为"中等"性能成本:

操作:实现对象
相对成本:中等
频率:查询返回的每个对象一次.

注释: 读取返回的DbDataReader对象并创建对象并设置基于DbDataRecord类的每个实例中的值的属性值的过程.如果对象已存在于ObjectContext中,并且查询使用AppendOnlyPreserveChanges合并选项,则此阶段不会影响性能.

换句话说:如果查询使用NoTracking合并选项,则此阶段确实会影响性能,并且残障更改跟踪的性能优势可能会因禁用身份管理和倍增对象实现的缺点而被破坏.

  • (慢拍)Aaaaand这就是为什么你有70k分.做得好. (8认同)
  • 它再次与 EF Core 3.0 相关。您的链接文档指出了此更改:“无跟踪查询 [...] 不执行身份解析。因此,即使相同的实体包含在多次结果。此行为在 EF Core 3.0 之前的版本中有所不同” (4认同)