demoshop

demo, trying to be the best_

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();
以上介紹兩個新語法都有非同步的版本,建議還是優先使用非同步版本。

回應討論