我的应用程序使用EntityFramework6.1.0和DbContextAPI。
它是一种计算机辅助设计系统,用来编辑一些工程文档。为了检测文档中的更改,我使用了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/。我建议你通读一下,这样你就可以很好地选择什么样的变更跟踪最适合你的应用程序。

10-02 14:49