DbContext.ChangeTracker.HasChanges 非常慢

Den*_*nis 5 c# entity-framework

我的应用程序使用实体框架 6.1.0 和DbContextAPI。

它是某种 CAD 系统,旨在编辑一些工程文档。为了检测文档中更改的事实,我正在使用DbContext.ChangeTracker.HasChanges.

当文档具有大量数据(大约 20-25 万个实体)时,DbContext.ChangeTracker.HasChanges运行速度非常慢。由于此代码用于启用/禁用“保存”命令,因此它从 UI 线程执行得相当频繁。这反过来又会影响应用程序的性能。

我重写了这个片段:

    private Lazy<DbContext> context;

    public bool HasChanges
    {
        get
        {
            if (!context.IsValueCreated)
            {
                return false;
            }

            return context.Value.ChangeTracker.HasChanges();
        }
    }
Run Code Online (Sandbox Code Playgroud)

对于这个:

    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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

而且(这是一个奇迹!)一切都运行得非常快。

看起来DbChangeTracker.HasChanges实施并不是最佳的。我错过了什么吗?

Art*_*ers 4

在第一个代码片段中,HasChanges 的调用链涉及对 DetectChanges 的调用。使用快照更改跟踪时,DetectChanges 会遍历所有跟踪的实体以确定是否有任何更改,以便 HasChanges 将返回正确的结果。

第二个代码片段不调用 DetectChanges,而只是向状态管理器询问它已经知道的状态。因此,如果实体已被修改但尚未检测到,则第二个代码片段可能会返回错误的结果。

有几种方法可以处理此问题,其中之一是使用更改跟踪代理而不是快照更改跟踪。我写了一个关于 DetectChanges 的博客系列,详细描述了各种选项和权衡:http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do /。我建议您仔细阅读,以便您可以就哪种更改跟踪最适合您的应用程序做出明智的选择。