2013-05-31 4 views
28

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

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

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

Entity Framework Версия: 5.0.0.0

DbContext класс

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

класс Controller

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! 

ответ

38

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

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

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

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

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

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

Извините, если это звучит все немного запутанно. Arthur Vickers can explain it better.

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

+0

я должен был прочитать более, что в несколько раз, но это поможет ответить на мой вопрос совсем немного, спасибо! Извините за ошибку копирования и вставки; я уточню вопрос для потомков. – Jesse

+1

К сожалению, «массовое добавление сущностей в цикле» - это когда вы хотите отключить отслеживание изменений. Это ускорение _massive_ (размер выборки 1, проверенный в моем приложении, но это была единственная разница между двумя запусками, добавляющими ~ 3000 строк). –

+1

@EdS .: Массовое добавление - одна из «простейших вещей», я имел в виду, где я на самом деле * бы * отключил автоматическое обнаружение изменений. – Slauma

1

согласно Entity Framework Automatic Detect Changes's 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.

+0

Если вы включите его в блоке finally, автоматически ли он делать то, что он сделал бы, если бы это было, но быстрее? –

2

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

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

context.ChangeTracker.AutoDetectChangesEnabled = false; 

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

context.ChangeTracker.AutoDetectChangesEnabled = true; 
Смежные вопросы