Подтвердить что ты не робот

DbContext AutoDetectChangesEnabled установлен на ложные обнаружения изменений

Я немного в тупике. Из того, что я прочитал, параметр DbContext.AutoDetectChangesEnabled to false должен отключить отслеживание изменений, требующее вызова DbContext.DetectChanges, чтобы идентифицировать изменения, которые необходимо отправить в базу данных.

Однако из моих журналов ниже видно, что изменения регистрируются с помощью трекера треков dbContexts, даже если установка установлена ​​в false.

Я что-то упустил?

Entity Framework Версия: 5.0.0.0

Класс DbContext

public class ProjectContext : DbContext {
    public DbSet<Project> Projects {get;set;}
}

Класс контроллера

private ProjectContext db = new ProjectContext();



public method(){
    Project p = new Project("uniqueName");
    db.Configuration.AutoDetectChangesEnabled = false;
    db.Projects.Add(p);
    DebugChangeTracker();
    db.SaveChanges();

    db.Projects.First().ProjectName = "a differentName!";
    DebugChangeTracker();
    db.SaveChanges();
}

Метод ведения журнала

    private void DebugChangeTracker()
    {
        var path = "C:\\mypath\\";
        path = path + Util.GetMsSinceEpoch().ToString() + "changeTracker.log";

        using (StreamWriter sw = new StreamWriter(path))
        {
            var changeTracker = db.ChangeTracker;
            var entries = changeTracker.Entries();
            foreach (var x in entries)
            {

                var name = x.Entity.ToString();
                var state = x.State;

                sw.WriteLine("");
                sw.WriteLine("***Entity Name: " + name +
                             "is in a state of " + state);
                var currentValues = x.CurrentValues;
                sw.WriteLine("***CurrentValues***");
                PrintPropertyValues(currentValues,sw);
                if (state != EntityState.Added)
                {
                    sw.WriteLine("***Original Values***");
                    PrintPropertyValues(x.OriginalValues,sw);
                }
            }
        }
    }

Первый журнал

***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName

Второй журнал

***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
4b9b3361

Ответ 1

Настройка AutoDetectChangesEnabled на false не отключает отслеживание изменений. (Что бы сделал метод расширения AsNoTracking()). Он просто отключает автоматический вызов DetectChanges, который в противном случае возникал бы во многих методах API DbContext.

Но DetectChanges - не единственный метод, который участвует в отслеживании изменений. Однако, если вы не вызываете его вручную в нужных местах, где это необходимо, состояния отслеживаемых сущностей являются неполными или неправильными, что приводит к неверно сохраненным данным.

В вашем случае ожидается состояние Added в первой части вашего method, даже если AutoDetectChangesEnabled установлен на false, потому что вы вызываете только db.Projects.Add(p). (В коде отсутствует код, но я думаю, что это просто ошибка копирования и вставки.) Вызов метода из DbContext отслеживается правильно, и состояния в трекере будут правильными, если состояние было правильным до вызовите Add.

Или другими словами: вызов метода API не превращает правильное состояние в неправильное состояние. Но: Если AutoDetectChangesEnabled есть false, он также не превратит неправильное состояние в правильное состояние, которое было бы в случае, если AutoDetectChangesEnabled - true.

Однако во второй части вашего method вы просто меняете значение свойства POCO. После этой точки состояние отслеживания изменений неверно (Unchanged) и без вызова DetectChanges (вручную или - если AutoDetectChangesEnabled - true - автоматически в ChangeTracker.Entries или SaveChanges), он никогда не будет отрегулирован, Эффект заключается в том, что измененное значение свойства не сохраняется в базе данных.

В последнем разделе, в котором упоминается состояние Unchanged, я ссылаюсь на свой собственный тест (а также на то, что я ожидаю). Я не знаю и не могу воспроизвести, почему у вас есть состояние Modified.

Извините, если это звучит немного запутанно. Артур Викерс может объяснить это лучше.

Я обнаружил автоматическое обнаружение изменений и поведение при отключении его довольно сложно понять и освоить, и я обычно не касаюсь значения по умолчанию (AutoDetectChangesEnabled= true) для любых отслеживаемых изменений, которые являются более сложными, чем простейшие вещи (например, добавление сущностей в цикле и т.д.).

Ответ 2

в соответствии с Entity Framework Automatic Detect Changes Article

они сказали:

вы можете добиться значительных улучшений производительности , отключив в some cases

посмотрите на этот пример из этой статьи

using (var context = new BloggingContext()) 
{ 
    try 
    { 
        context.Configuration.AutoDetectChangesEnabled = false; 

        // Make many calls in a loop 
        foreach (var blog in aLotOfBlogs) 
        { 
            context.Blogs.Add(blog); 
        } 
    } 
    finally 
    { 
        context.Configuration.AutoDetectChangesEnabled = true; 
    }
}

Этот код избегает ненужных вызовов DetectChanges, которые произошли при вызове методов DbSet.Add и SaveChanges.

Ответ 3

Если кто-то ищет AutoDetectChangesEnabled в ядре Entity Framework Core, вы можете найти его под ChangeTracker insted из Configuration

Использование:

context.ChangeTracker.AutoDetectChangesEnabled = false;

//Do something here
context.PriceRecords.Add(newPriceRecord);

context.ChangeTracker.AutoDetectChangesEnabled = true;