DbContext AutoDetectChangesEnabled设置为false检测更改

Jes*_*sse 44 entity-framework dbcontext entity-framework-5

我有点难过.根据我的阅读设置DbContext.AutoDetectChangesEnabled,false应该禁用需要调用的更改跟踪DbContext.DetectChanges,以便识别要发送到数据库的更改.

但是,从我的下面的日志中可以清楚地看到,dbContexts更改跟踪器正在注册更改,即使设置为false也是如此.

我错过了什么吗?

实体框架版本:5.0.0.0

DbContext类

public class ProjectContext : DbContext {
    public DbSet<Project> Projects {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

控制器类

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

记录方法

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

第一次登录

***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName
Run Code Online (Sandbox Code Playgroud)

第二个日志

***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
Run Code Online (Sandbox Code Playgroud)

Sla*_*uma 56

设置AutoDetectChangesEnabledfalse不禁用更改跟踪.(这就是AsNoTracking()扩展方法的作用.)它只是禁用自动调用DetectChanges,否则会在许多DbContextAPI方法中发生.

但这DetectChanges不是参与变更跟踪的唯一方法.但是,如果您不在需要它的正确位置手动调用它,则跟踪的实体状态不完整或错误导致错误保存的数据.

在你的情况下Added,你的第一部分的状态method是预期的,即使AutoDetectChangesEnabled设置为,false因为你只是打电话db.Projects.Add(p).(你的代码btw中缺少该行,但我想这只是一个复制和粘贴错误.)调用DbContextAPI中的方法跟踪更改正确,如果调用之前状态正确,则跟踪器中的状态将是正确的Add.

或者换句话说:调用API方法不会将正确的状态转换为错误的状态.但是,如果AutoDetectChangesEnabledfalse它也不会变成错误的状态进入,如果这将是情况下,正确的状态AutoDetectChangesEnabledtrue.

但是,在您的第二部分中,您method只是更改了POCO属性值.在此之后,更改跟踪器状态是错误的(Unchanged)并且没有调用DetectChanges(手动或 - 如果AutoDetectChangesEnabledtrue- 自动进入ChangeTracker.EntriesSaveChanges),它将永远不会被调整.结果是更改的属性值未保存到数据库.

在最后一节提到状态,Unchanged我指的是我自己的测试(以及我期望的).我不知道也无法重现为什么你有州Modified.

对不起,如果这听起来有点令人困惑.亚瑟维克斯可以更好地解释它.

我发现自动更改检测和禁用它时的行为相当难以理解和掌握,我通常不会触及默认(AutoDetectChangesEnabled= true)任何比最简单的事情更复杂的跟踪更改(如在循环中批量添加实体)等).

  • 不幸的是,“在循环中批量添加实体”是当您想要禁用更改跟踪时。这是一个巨大的加速(样本大小为 1,在我的应用程序中进行了测试,但这是两次运行之间添加 ~3000 行的唯一区别)。 (2认同)
  • @EdS.:批量添加是“最简单的事情”之一,我的意思是我实际上*会*禁用自动更改检测。 (2认同)

小智 14

如果有人AutoDetectChangesEnabled在Entity Framework Core中寻找,你可以在ChangeTrackerinsted 框架下找到它Configuration

用法如下:

context.ChangeTracker.AutoDetectChangesEnabled = false;

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

context.ChangeTracker.AutoDetectChangesEnabled = true;
Run Code Online (Sandbox Code Playgroud)


Bas*_*ANI 5

根据实体框架自动检测更改的文章

他们说:

你可能会得到显著的性能改进通过将其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; 
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码避免了DetectChanges在调用DbSet.AddSaveChanges方法时发生的不必要的调用.

  • 如果你在finally块中重新打开它,它是否会自动执行它已经完成的操作,如果它已经开启但更快? (4认同)