我的应用程序使用EntityFramework6.1.0和DbContext
API。
它是一种计算机辅助设计系统,用来编辑一些工程文档。为了检测文档中的更改,我使用了DbContext.ChangeTracker.HasChanges
。
当文档有大量数据(大约20-25个实体)时,DbContext.ChangeTracker.HasChanges
运行非常慢。由于此代码用于启用/禁用“save”命令,因此它经常从ui线程执行。这反过来又会影响应用程序的性能。
我重新写下了这个片段:
private Lazy<DbContext> context;
public bool HasChanges
{
get
{
if (!context.IsValueCreated)
{
return false;
}
return context.Value.ChangeTracker.HasChanges();
}
}
对于这个:
public bool HasChanges
{
get
{
if (!context.IsValueCreated)
{
return false;
}
var objectStateManager = ((IObjectContextAdapter)context.Value).ObjectContext.ObjectStateManager;
return
objectStateManager.GetObjectStateEntries(EntityState.Added).Any() ||
objectStateManager.GetObjectStateEntries(EntityState.Deleted).Any() ||
objectStateManager.GetObjectStateEntries(EntityState.Modified).Any();
}
}
(这是个奇迹!)一切都非常快。
看来
DbChangeTracker.HasChanges
的实现不是最佳的。我遗漏了什么吗?
最佳答案
在第一个代码片段中,对haschanges的调用链涉及对detectchanges的调用。使用快照更改时,跟踪检测更改将遍历所有被跟踪的实体,以确定是否有任何更改,以便HasChanges将返回正确的结果。
第二个代码片段不调用detectchanges,而只是询问状态管理器它已经知道的状态。因此,如果实体已被修改但尚未检测到,则第二个代码段可能返回错误的结果。
有几种处理方法,其中之一是使用变更跟踪代理代替快照更改跟踪。我写了一个关于detectchanges的博客系列,详细描述了各种选项和权衡:http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/。我建议你通读一下,这样你就可以很好地选择什么样的变更跟踪最适合你的应用程序。