在 EF Core 7.0 中針對大量更新與大量刪除的效能改善
- 2023-02-01
- 5404
- 0
Entity Framework 大幅簡化開發人員操作資料庫的工作,在單筆操作時 Entity Framework 非常舒服好寫,但遇到了需要大量更新和大量刪除的情境時 ORM 的特性反而顯的好像有點累贅並且消耗大量效能,好在這問題在 Entity Framework Core 7 的時候有了官方解。
在 Entity Framework Core7 之前要大量(批次)更新需要這樣寫
var source=DimCustomer.Where(d=>d.MiddleName=="C").ToList();
foreach (var item in source)
{
item.MiddleName="CC";
}
SaveChanges();
- 第一行將需要的資料取出,且會被 EF 追蹤更新。
- foreach 的操作是記憶體內的資料。
- SaveChanges 才會將異動反應至資料庫內。
這有什麼問題?在此情境中我們根本不需要追蹤機制,但預設就是會追蹤,比較熟的開發者應該知道可以加上.AsNoTracking()
來明確宣告不要追蹤,但還是浪費了把資料抓回來的記憶體,新版的語法就是要來解決這問題,以下來看看新語法
ExecuteUpdate
DimCustomer.Where(d=>d.MiddleName=="C")
.ExecuteUpdate(s=>s.SetProperty(p=>p.MiddleName,"CC"));
產生的 SQL 語法如下
UPDATE [d]
SET [d].[MiddleName] = N'CC'
FROM [DimCustomer] AS [d]
WHERE [d].[MiddleName] = N'C'
它是利用 LINQ 寫查詢語句,然後直接將轉換後的 SQL 語法傳給資料庫執行,所以不會將資料載入記憶體,也自然沒有變更追蹤,藉此達到更有效率的更新語法。而且可以看到以上範例是沒有呼叫SaveChanges
方法的。
再提供一個常見的用法,在設定值的時候可以參考其他欄位的值
DimCustomer.Where(d=>d.MiddleName=="C")
.ExecuteUpdate(s=>s.SetProperty(p=>p.MiddleName,p=>p.FirstName+"CC"+p.LastName));
原理已經瞭解後批次刪除應該就沒什麼好講的了,記得前面是查詢語法,你可以利用 LINQ 寫好需要的查詢條件再呼叫ExecuteDelete
執行。
ExecuteDelete
DimCustomer.Where(d=>d.MiddleName=="CC").ExecuteDelete();
回應討論