Bagikan melalui


Pembaruan Efisien

Pengelompokan

EF Core membantu meminimalkan perjalanan pulang pergi dengan secara otomatis mengumpulkan semua pembaruan dalam satu perjalanan pulang pergi. Pertimbangkan hal berikut:

var blog = await context.Blogs.SingleAsync(b => b.Url == "http://someblog.microsoft.com");
blog.Url = "http://someotherblog.microsoft.com";
context.Add(new Blog { Url = "http://newblog1.microsoft.com" });
context.Add(new Blog { Url = "http://newblog2.microsoft.com" });
await context.SaveChangesAsync();

Di atas memuat blog dari database, mengubah URL-nya, lalu menambahkan dua blog baru; untuk menerapkan ini, dua pernyataan SQL INSERT dan satu pernyataan UPDATE dikirim ke database. Daripada mengirim setiap instans Blog satu per satu, EF Core melacak perubahan-perubahan ini secara internal dan mengeksekusinya dalam satu proses saat SaveChanges dipanggil.

Jumlah pernyataan yang dibatch oleh EF dalam satu putaran komunikasi tergantung pada penyedia database yang dipakai. Misalnya, analisis performa telah menunjukkan batching umumnya kurang efisien untuk SQL Server ketika kurang dari 4 pernyataan terlibat. Demikian pula, manfaat batching berkurang setelah sekitar 40 pernyataan untuk SQL Server, maka secara default EF Core hanya akan mengeksekusi hingga 42 pernyataan dalam satu batch, dan pernyataan tambahan dieksekusi dalam pengiriman terpisah.

Pengguna juga dapat mengubah ambang batas ini untuk mencapai performa yang berpotensi lebih tinggi - tetapi tolok ukur dengan hati-hati sebelum memodifikasi ini:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True",
        o => o
            .MinBatchSize(1)
            .MaxBatchSize(100));
}

Gunakan ExecuteUpdate dan ExecuteDelete jika relevan

Mari kita asumsikan Anda ingin memberi semua karyawan Anda kenaikan gaji. Implementasi umum untuk ini di EF Core akan terlihat seperti berikut:

foreach (var employee in context.Employees)
{
    employee.Salary += 1000;
}
await context.SaveChangesAsync();

Meskipun ini adalah kode yang valid dengan sempurna, mari kita analisis apa yang dilakukannya dari perspektif performa:

  • Roundtrip basis data sedang dilakukan, untuk memuat semua karyawan yang relevan; perhatikan bahwa ini membawa semua data baris pegawai ke sistem klien, meskipun hanya data gaji yang sebenarnya diperlukan.
  • Pelacakan perubahan EF Core akan membuat cuplikan saat memuat entitas, lalu membandingkan cuplikan tersebut dengan instans untuk mengetahui properti mana yang berubah.
  • Biasanya, roundtrip database kedua dilakukan untuk menyimpan semua perubahan (perhatikan bahwa beberapa penyedia database membagi perubahan menjadi beberapa roundtrip). Meskipun perilaku batching ini jauh lebih baik daripada melakukan pulang pergi untuk setiap pembaruan, EF Core masih mengirim pernyataan UPDATE per karyawan, dan database harus menjalankan setiap pernyataan secara terpisah.

Dimulai dengan EF Core 7.0, Anda dapat menggunakan metode ExecuteUpdateAsync dan ExecuteDeleteAsync untuk melakukan hal yang sama jauh lebih efisien:

await context.Employees.ExecuteUpdateAsync(s => s.SetProperty(e => e.Salary, e => e.Salary + 1000));

Ini mengirimkan pernyataan SQL berikut ke database:

UPDATE [Employees] SET [Salary] = [Salary] + 1000;

Ini UPDATE melakukan seluruh operasi dalam satu kali, tanpa memuat atau mengirim data aktual ke database, dan tanpa menggunakan mekanisme pelacakan perubahan EF, yang memberikan tambahan overhead. Untuk informasi selengkapnya, lihat ExecuteUpdate dan ExecuteDelete.

Jika Anda menggunakan versi EF Core yang lebih lama yang belum mendukung ExecuteUpdate dan ExecuteDelete, atau ingin menjalankan pernyataan SQL kompleks yang tidak didukung oleh metode ini, Anda masih dapat menggunakan kueri SQL untuk melakukan operasi:

context.Database.ExecuteSql($"UPDATE [Employees] SET [Salary] = [Salary] + 1000");

Untuk mempelajari selengkapnya tentang perbedaan antara SaveChanges dan ExecuteUpdate/ExecuteDelete, lihat halaman Gambaran Umum tentang menyimpan data.