Pertanyaan DbContext AutoDetectChangesEnabled disetel ke perubahan mendeteksi yang salah


Saya agak bingung. Dari apa yang saya baca pengaturan DbContext.AutoDetectChangesEnabled untuk false harus menonaktifkan pelacakan perubahan yang mengharuskan seseorang untuk menelepon DbContext.DetectChanges untuk mengidentifikasi perubahan yang akan dikirim ke database.

Namun, jelas dari log saya di bawah ini bahwa perubahan sedang didaftarkan oleh pelacak perubahan dbContexts, bahkan dengan pengaturan diatur ke false.

Apakah saya kehilangan sesuatu?

Versi Kerangka Entitas: 5.0.0.0

Kelas DbContext

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

Kelas pengontrol

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

Metode penebangan

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

Log pertama

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

Log Kedua

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

32
2018-05-31 18:13


asal


Jawaban:


Pengaturan AutoDetectChangesEnabled untuk false tidak menonaktifkan pelacakan perubahan. (Itulah yang terjadi AsNoTracking() metode ekstensi akan dilakukan.) Ini hanya menonaktifkan panggilan otomatis DetectChanges yang sebaliknya akan terjadi pada banyak orang DbContext Metode API.

Tapi DetectChanges bukan satu-satunya metode yang berpartisipasi dalam pelacakan perubahan. Namun, jika Anda tidak menyebutnya secara manual di tempat yang tepat di mana diperlukan, status entitas yang dilacak tidak lengkap atau salah menyebabkan data yang salah disimpan.

Dalam kasus Anda negara Added di bagian pertama dari Anda method diharapkan, bahkan dengan AutoDetectChangesEnabled mulai false karena Anda hanya menelepon db.Projects.Add(p). (Garis ini hilang dalam kode btw Anda, tapi saya kira itu hanya kesalahan salin dan tempel.) Memanggil metode dari DbContext Trek API berubah dengan benar dan status di pelacak akan benar jika keadaan benar sebelum panggilan dihubungi Add.

Atau dengan kata lain: Memanggil metode API tidak mengubah status yang benar menjadi negara yang salah. Tapi jika AutoDetectChangesEnabled aku s false itu juga tidak akan mengubah keadaan yang salah menjadi keadaan yang benar yang akan terjadi jika AutoDetectChangesEnabled aku s true.

Namun, di bagian kedua Anda method Anda hanya mengubah nilai properti POCO. Setelah titik ini, status pelacak perubahan salah (Unchanged) dan tanpa panggilan ke DetectChanges (secara manual atau - jika AutoDetectChangesEnabled aku s true - secara otomatis masuk ChangeTracker.Entries atau SaveChanges) itu tidak akan pernah disesuaikan. Efeknya adalah bahwa nilai properti yang diubah tidak disimpan ke database.

Di bagian terakhir menyebutkan negara Unchanged Saya mengacu pada tes saya sendiri (dan juga untuk apa yang saya harapkan). Saya tidak tahu dan tidak dapat mereproduksi mengapa Anda memiliki negara Modified.

Maaf, jika ini terdengar agak membingungkan. Arthur Vickers dapat menjelaskannya dengan lebih baik.

Saya menemukan deteksi perubahan otomatis dan perilaku ketika melumpuhkannya agak sulit untuk dipahami dan dikuasai dan saya biasanya tidak menyentuh default (AutoDetectChangesEnabled = true) untuk setiap perubahan yang terlacak yang lebih kompleks daripada hal-hal sederhana (seperti menambahkan entitas secara massal dalam satu lingkaran, dll.).


41
2018-05-31 20:39



menurut Entitas Kerangka Otomatis Mendeteksi Perubahan Artikel 

mereka berkata:

Anda mungkin menjadi signifikan peningkatan kinerja dengan memutarnya mati di some cases

lihat contoh ini dari artikel itu

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

Kode ini menghindari panggilan yang tidak perlu DetectChanges yang akan terjadi saat memanggil DbSet.Adddan SaveChanges metode.


3
2017-10-06 13:04



Jika seseorang mencari AutoDetectChangesEnabled dalam Entity Framework Core Anda dapat menemukannya di bawah ChangeTracker insted dari Configuration

Penggunaan seperti:

context.ChangeTracker.AutoDetectChangesEnabled = false;

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

context.ChangeTracker.AutoDetectChangesEnabled = true;

2
2017-07-27 09:44