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