Verimli Güncelleştirme
Toplu işleme
EF Core, tüm güncelleştirmeleri tek bir gidiş dönüşte otomatik olarak toplu işleyerek gidiş dönüşleri en aza indirmeye yardımcı olur. Aşağıdakileri göz önünde bulundurun:
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();
Yukarıdaki, veritabanından bir blog yükler, URL'sini değiştirir ve ardından iki yeni blog ekler; bunu uygulamak için veritabanına iki SQL INSERT deyimi ve bir UPDATE deyimi gönderilir. Blog örnekleri eklendikçe bunları tek tek göndermek yerine EF Core bu değişiklikleri dahili olarak izler ve SaveChanges çağrıldığında tek bir gidiş dönüşte yürütür.
EF'in tek bir gidiş dönüş sırasında toplu iş yaptığı deyimlerin sayısı, kullanılan veritabanı sağlayıcısına bağlıdır. Örneğin performans analizi, 4'ten az deyim söz konusu olduğunda toplu işlemlerin SQL Server için genel olarak daha az verimli olduğunu göstermiştir. Benzer şekilde, SQL Server için yaklaşık 40 deyimden sonra toplu işlemlerin avantajları azalır, bu nedenle EF Core varsayılan olarak tek bir toplu işlemde en fazla 42 deyim yürütür ve ayrı gidiş dönüşlerde ek deyimler yürütür.
Kullanıcılar ayrıca, potansiyel olarak daha yüksek performans elde etmek için bu eşikleri değiştirebilir, ancak bunları değiştirmeden önce dikkatli bir şekilde karşılaştırma yapabilir:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True",
o => o
.MinBatchSize(1)
.MaxBatchSize(100));
}
Uygun olduğunda ExecuteUpdate ve ExecuteDelete kullanma
Tüm çalışanlarınıza zam yapmak istediğinizi varsayalım. EF Core'da bunun tipik bir uygulaması aşağıdaki gibi görünür:
foreach (var employee in context.Employees)
{
employee.Salary += 1000;
}
await context.SaveChangesAsync();
Bu tamamen geçerli bir kod olsa da performans açısından ne yaptığını analiz edelim:
- İlgili tüm çalışanları yüklemek için bir veritabanı gidiş dönüş işlemi yapılır; yalnızca maaş gerekiyorsa bile, bunun tüm çalışanların satır verilerini müşteriye getirdiğini unutmayın.
- EF Core'un değişiklik izlemesi, varlıkları yüklerken anlık görüntüler oluşturur ve ardından hangi özelliklerin değiştiğini bulmak için bu anlık görüntüleri örneklerle karşılaştırır.
- Genellikle, tüm değişiklikleri kaydetmek için ikinci bir veritabanı sorgusu gerçekleştirilir (bazı veritabanı sağlayıcılarının değişiklikleri birden fazla sorguya böldüğüne dikkat edin). Bu toplu işlem davranışı her güncelleştirme için gidiş dönüş yapmaktan çok daha iyi olsa da, EF Core yine de çalışan başına bir UPDATE deyimi gönderir ve veritabanının her deyimi ayrı olarak yürütmesi gerekir.
EF Core 7.0'dan başlayarak, aynı şeyi çok daha verimli bir şekilde yapmak için ExecuteUpdateAsync
ve ExecuteDeleteAsync
yöntemlerini kullanabilirsiniz:
await context.Employees.ExecuteUpdateAsync(s => s.SetProperty(e => e.Salary, e => e.Salary + 1000));
Bu, veritabanına aşağıdaki SQL deyimini gönderir:
UPDATE [Employees] SET [Salary] = [Salary] + 1000;
Bu UPDATE
, tüm işlemi veritabanına herhangi bir gerçek veri yüklemeden veya göndermeden ve EF'nin ek yük oluşturan değişiklik izleme makinelerinden yararlanmadan tek bir gidiş dönüşte gerçekleştirir. Daha fazla bilgi için bkz. ExecuteUpdate
ve ExecuteDelete
.
EF Core'un henüz ExecuteUpdate
ve ExecuteDelete
desteklemeyen eski bir sürümünü kullanıyorsanız veya bu yöntemler tarafından desteklenmeyen karmaşık bir SQL deyimi yürütmek istiyorsanız, işlemi gerçekleştirmek için bir SQL sorgusu kullanmaya devam edebilirsiniz:
context.Database.ExecuteSql($"UPDATE [Employees] SET [Salary] = [Salary] + 1000");