DbContext AutoDetectChangesEnabled значение false обнаружение изменений

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

однако из моих журналов ниже ясно, что изменения регистрируются dbcontexts change tracker, даже с настройкой false.

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

Entity Framework Версия: 5.0.0.0

DbContext можно класс!--9-->

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!

3 ответов


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

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

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

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

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

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

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

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


по лицу Framework автоматическое обнаружение изменений в статье

они сказали:

вы можете получить значительные производительность поворотом выкл на 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 методы.


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

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

context.ChangeTracker.AutoDetectChangesEnabled = false;

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

context.ChangeTracker.AutoDetectChangesEnabled = true;