Sdílet prostřednictvím


Efektivní aktualizace

Dávkování

EF Core pomáhá minimalizovat zaokrouhlování tím, že automaticky seskupí všechny aktualizace v rámci jednoho kruhového převodu. Vezměte v úvahu následující skutečnosti:

var blog = context.Blogs.Single(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" });
context.SaveChanges();

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 tyto změny posílaly jednotlivě, protože se přidají instance blogu, EF Core tyto změny interně sleduje a při zavolání je spustí v jednom kruhovém rozjezdu SaveChanges .

Počet příkazů, které ef batches v jednom zaokrouhlování závisí na používaném poskytovateli databáze. Například analýza výkonu ukázala, že dávkování je obecně méně efektivní pro SQL Server, pokud se týká méně než 4 příkazů. Podobně výhody dávkového snížení výkonu 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 provede další příkazy v samostatných zaokrouhlování.

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

I když je to dokonale platný kód, pojďme analyzovat, co dělá z hlediska výkonu:

  • Provede se zaokrouhlit databáze, aby se načetli všichni relevantní zaměstnanci; Všimněte si, že to klientovi přináší všechna data řádků zaměstnanců, i když bude potřeba jenom mzda.
  • 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é zaokrouhlení databáze (upozorňujeme, že někteří poskytovatelé databáze změny rozdělí na násobky zaokrouhlit). I když je toto dávkové chování mnohem lepší než provádění přeokrouhlování 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 pomocí ExecuteUpdate ExecuteDelete metod provádět totéž mnohem efektivněji:

context.Employees.ExecuteUpdate(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;

Tím UPDATE se provede celá operace v jednom kruhovém provozu, aniž by se do databáze načítala nebo neodesílala žádná skutečná data, a bez použití zařízení EF pro sledování změn, což představuje další režii. Další informace najdete v tématech ExecuteUpdate a ExecuteDelete.

Pokud používáte starší verzi EF Core, která ještě nepodporuje ExecuteUpdate a ExecuteDeletenebo 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 daty a ExecuteUpdateExecuteDelete/najdete na stránce Přehled při ukládání dat.