我有一种奇怪的行为,试图执行一个将ObjectQuery MergeOption声明为“NoTracking”的查询,在这种情况下,实体框架不应附加任何实体,也不应创建相对的ObjectStateEntry来跟踪实体状态。
问题在于,不是增加性能而是变得更糟,相同的查询在默认合并(即AppendingOnly)时需要10秒,如果我尝试指定notracking则需要1分钟
有人对此有解释吗?
答案 0 :(得分:141)
如果通过设置NoTracking
合并选项来禁用更改跟踪,则可以节省将对象附加到上下文的性能成本,但另一方面也会丢失身份管理。
这意味着可能会有更多的对象 - 许多具有相同键的对象 - 将被实现。
示例:假设您有一个User
实体,其中Roles
集合作为导航属性。还假设您在数据库中有100万用户,并且所有用户都处于相同的10个角色中,即每个用户都有一个包含10个元素的角色集合。如果您运行以下查询...
var users = context.Users.Include("Roles").ToList();
...具体化和实例化对象的数量取决于合并选项:
如果你不使用NoTracking
,你将在内存中拥有1.000.010个对象,即100万个用户,但只有10个角色,因为身份映射将确保每个密钥只有1个角色被实现,附在上下文中。所有用户的Roles
集合使用相同的10个角色实例。
但是,如果使用NoTracking
,则EF不会将对象附加到上下文,因此身份管理被禁用,内存中将有11.000.000个对象:每个用户100万个,角色实例10个用户,即1000万个角色对象。因此,物化附加到上下文时,物化对象的数量将超过10倍。
对象实现分类为"moderate" performance costs:
操作:实现对象
相对成本:中等
频率:查询返回的每个对象一次。
的评论:强> 读取返回的DbDataReader对象并创建的过程 对象和设置基于值的属性值 DbDataRecord类的每个实例。 如果对象已存在 在ObjectContext中,查询使用 AppendOnly 或 PreserveChanges 合并选项,此阶段不会影响效果。
换句话说:如果查询使用NoTracking
合并选项,则此阶段确实会影响性能,并且可能会因缺陷而破坏已禁用的更改跟踪的性能优势残疾人身份管理和倍增对象物化。