Efektivní aktualizace
Dávkování
EF Core pomáhá minimalizovat počet cest tam a zpět tím, že automaticky seskupí všechny aktualizace v rámci jediné cesty tam a zpět. Vezměte v úvahu následující skutečnosti:
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();
Výše uvedené načte blog z databáze, změní jeho adresu URL a pak přidá dva nové blogy; k použití tohoto příkazu se do databáze odešlou dva příkazy SQL INSERT a jeden příkaz UPDATE. Místo toho, aby se instance blogu přidávaly jedna po druhé, EF Core tyto změny interně sleduje a provede je v jednom průchodu, když je volán SaveChanges.
Počet příkazů, které EF zpracovává v jednom cyklu cesty tam a zpět, závisí na poskytovateli databáze, který se používá. Například analýza výkonu ukázala, že dávkování je pro SQL Server obecně méně efektivní, když se jedná o méně než 4 příkazy. Podobně se přínosy dávkování snižují po přibližně 40 příkazech pro SQL Server, takže EF Core ve výchozím nastavení spustí až 42 příkazů v jedné dávce a další příkazy provede v samostatných cyklech.
Uživatelé také můžou tyto prahové hodnoty upravit, aby dosáhli potenciálně vyššího výkonu, ale před úpravou těchto hodnot pečlivě proveďte srovnávací testy:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True",
o => o
.MinBatchSize(1)
.MaxBatchSize(100));
}
Použití ExecuteUpdate a ExecuteDelete, pokud jsou relevantní
Předpokládejme, že chcete všem svým zaměstnancům dát zvýšení. Typická implementace pro tuto implementaci v EF Core by vypadala takto:
foreach (var employee in context.Employees)
{
employee.Salary += 1000;
}
await context.SaveChangesAsync();
I když je to dokonale platný kód, pojďme analyzovat, co dělá z hlediska výkonu:
- Provede se dotaz do databáze, aby se načetli všichni relevantní zaměstnanci; Upozorňujeme, že to přenáší ke klientovi všechna data o zaměstnancích, i když bude potřeba jen plat.
- Sledování změn EF Core vytváří snímky při načítání entit a pak tyto snímky porovnává s instancemi a zjistí, které vlastnosti se změnily.
- Za účelem uložení všech změn se obvykle provádí druhý přístup k databázi (upozorňujeme, že někteří poskytovatelé databáze mohou změny rozdělit do více přístupů). I když je toto dávkové zpracování mnohem lepší než provádění jednoho dotazu pro každou aktualizaci, EF Core stále odesílá příkaz UPDATE pro každého zaměstnance a databáze musí každý příkaz spouštět samostatně.
Počínaje EF Core 7.0 můžete použít ExecuteUpdateAsync
a ExecuteDeleteAsync
metody, abyste to udělali mnohem efektivněji:
await context.Employees.ExecuteUpdateAsync(s => s.SetProperty(e => e.Salary, e => e.Salary + 1000));
Tím se do databáze odešle následující příkaz SQL:
UPDATE [Employees] SET [Salary] = [Salary] + 1000;
Tato UPDATE
provádí celou operaci v jednom cyklu, aniž by načítala nebo odesílala jakákoli skutečná data do databáze, a bez použití mechanismu EF pro sledování změn, což znamená další zatížení. Další informace najdete v tématu ExecuteUpdate
a ExecuteDelete
.
Pokud používáte starší verzi EF Core, která ještě nepodporuje ExecuteUpdate
a ExecuteDelete
, nebo chcete spustit složitý příkaz SQL, který tyto metody nepodporuje, můžete k provedení operace použít dotaz SQL:
context.Database.ExecuteSql($"UPDATE [Employees] SET [Salary] = [Salary] + 1000");
Další informace o rozdílech mezi SaveChanges
a ExecuteUpdate
/ExecuteDelete
najdete na stránce přehledu při ukládání dat.