DbContext.ChangeTracker.HasChanges is very slow

My application uses Entity Framework 6.1.0 and DbContextAPI.

This is some kind of CAD system, and it is intended for editing some technical documents. To detect the fact of changes in the document, I use DbContext.ChangeTracker.HasChanges.

When a document has a large amount of data (approximately 20-25 thousand objects), it DbContext.ChangeTracker.HasChangesworks very slowly . Since this code is used to enable / disable the Save command, it is quite often executed from the user interface thread. This, in turn, affects application performance.

I rewrote this snippet:

    private Lazy<DbContext> context;

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

            return context.Value.ChangeTracker.HasChanges();
        }
    }

to that:

    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();
        }
    }

and (this is a miracle!) everything works very fast.

, DbChangeTracker.HasChanges . - ?

+4
2

HasChanges DetectChanges. DetectChanges , , - , HasChanges .

DetectChanges, , . , , , .

, - . DetectChanges, : http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/. , , .

+3

@Dennis, Detect changes . , 1000 , , , , 1 . , ,

 1 + 2 + 3 + ... + 999 + 1000

or:

N(N+1)/2

N 25 000; . O (N ^ 2), .. O - N, , .

25 000 , .. , , - 25 000 1 LOC, N (N + 1)/2. , .

objectStateManager.GetObjectStateEntries(EntityState.Added).Any() ||
                objectStateManager.GetObjectStateEntries(EntityState.Deleted).Any() ||
                objectStateManager.GetObjectStateEntries(EntityState.Modified).Any()
+2
source

Source: https://habr.com/ru/post/1543009/


All Articles