共用方式為


有效率的更新

批次處理

EF Core 可透過在單一往返中自動批次處理所有更新,以協助將往返時間降到最低。 請考量下列各項:

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

上述會從資料庫載入部落格、變更其 URL,然後新增兩個新的部落格:若要套用這項功能,則會將兩個 SQL INSERT 語句和一個 UPDATE 語句傳送至資料庫。 EF Core 會在內部追蹤這些變更,而不是逐一傳送這些變更,並在呼叫 時 SaveChanges 以單一往返方式執行這些變更。

EF 批次在單次往返中的語句數目取決於所使用的資料庫提供者。 例如,當涉及少於 4 個語句時,效能分析已顯示批次處理對 SQL Server 而言通常效率較低。 同樣地,在 SQL Server 大約 40 個語句之後批次處理的優點會降低,因此 EF Core 預設只會在單一批次中執行最多 42 個語句,並在個別往返中執行其他語句。

使用者也可以調整這些臨界值,以達到可能更高的效能 -- 但在修改這些值之前,請謹慎基準測試:

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

相關時使用 ExecuteUpdate 和 ExecuteDelete

假設您想要向所有員工提供加薪。 EF Core 中這個的一般實作如下所示:

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

雖然這是完全有效的程式碼,但讓我們從效能的觀點來分析其用途:

  • 執行資料庫往返,以載入所有相關員工;請注意,這會將所有 Employees 的資料列資料帶入用戶端,即使只需要薪資也一樣。
  • EF Core 的變更追蹤會在載入實體時建立快照集,然後將這些快照集與實例進行比較,以找出哪些屬性已變更。
  • 一般而言,會執行第二個資料庫往返以儲存所有變更(請注意,某些資料庫提供者會將變更分割成往返倍數)。 雖然此批次處理行為遠勝於每次更新往返,但 EF Core 仍會為每個員工傳送 UPDATE 語句,而且資料庫必須個別執行每個語句。

從 EF Core 7.0 開始,您可以使用 ExecuteUpdateExecuteDelete 方法來更有效率地執行相同動作:

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

這會將下列 SQL 語句傳送至資料庫:

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

這會 UPDATE 在單次往返中執行整個作業,而不需要載入或傳送任何實際資料至資料庫,而不需使用 EF 的變更追蹤機制,這會產生額外的額外負荷。 如需詳細資訊,請參閱 ExecuteUpdateExecuteDelete

如果您使用尚未支援 ExecuteUpdateExecuteDelete 的舊版 EF Core,或想要執行這些方法不支援的複雜 SQL 語句,您仍然可以使用 SQL 查詢來執行作業:

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

若要深入瞭解 和 /ExecuteDeleteExecuteUpdate 之間的差異 SaveChanges ,請參閱 儲存資料的概觀頁面。