**背景** 小編最近接到一個任務,批量獲取內部網站用TXT生成的日誌,在閑時把日誌插入到MySql資料庫做分析。為了快速開發小編選擇了Entity Framework Core,很快開發完成了。測試數據不是很多,批量插入數據很快完成,效率很高。但是部署到線上問題來了,最開始也挺快,越到後面越慢,慢 ...
背景
小編最近接到一個任務,批量獲取內部網站用TXT生成的日誌,在閑時把日誌插入到MySql資料庫做分析。為了快速開發小編選擇了Entity Framework Core,很快開發完成了。測試數據不是很多,批量插入數據很快完成,效率很高。但是部署到線上問題來了,最開始也挺快,越到後面越慢,慢的無法接受。於是查詢了一下官網和某度,只需加一句代碼就可以讓EF批量插入數據飆升。
代碼示例
開始的批量添加代碼:
public async void AddRangeAsync(List<T> entities)
{
await _dbContext.AddRangeAsync(entities);
await _dbContext.SaveChangesAsync();
}
在以上方法增加一行,如下:
public async void AddRangeAsync(List<T> entities)
{
//批量添加需要將AutoDetectChangesEnabled給位false
_dbContext.ChangeTracker.AutoDetectChangesEnabled = false;
await _dbContext.AddRangeAsync(entities);
await _dbContext.SaveChangesAsync();
}
原理
微軟的解釋:“AutoDetectChangesEnabled預設值為 true。這可確保上下文在執行操作(例如 SaveChanges() 或返回更改跟蹤信息)之前瞭解對跟蹤實體實例所做的任何更改。如果禁用自動檢測更改, DetectChanges() 則必須確保在修改實體實例時調用 。如果不這樣做,可能會導致某些更改在返回或返回過時的更改跟蹤信息期間 SaveChanges() 無法持久保存”[1]。
這是啥意思呢?ChangeTracker的AutoDetectChangesEnabled屬性是Entity Framework中的一個屬性,用於控制是否自動檢測實體的更改。預設情況下,AutoDetectChangesEnabled屬性的值為true,即自動檢測更改。每次對實體進行更改(添加、刪除、更新)時,Entity Framework會自動檢測這些更改,並將其標記為“已更改”。這樣,在調用SaveChanges方法時,Entity Framework會自動將這些更改應用到資料庫中。
當AutoDetectChangesEnabled屬性的值為true時,將對EF的性能造成一定的影響,尤其是批量插入數據。對於插入操作,無論AutoDetectChangesEnabled的值為true還是false,都可以成功插入數據。因為插入操作本身就是一種新增操作,無需進行實體的更改檢測。所以在批量插入時,建議把AutoDetectChangesEnabled設置為false。
設置為false具體對操作的數據有沒有影響呢?答案是肯定的,分情況。如果插入數據後有上下文操作,那麼上下文不會自動更新實體的狀態,如果沒有後續操作可以忽略。這就需要手動調用DetectChanges方法或將實體狀態設置為“已更改”才能使上下文與資料庫同步。建議批量插入數據結束時,把AutoDetectChangesEnabled的值改為true。
**結語
**
本文講述了.NET用EF批量插入數據,改進性能的簡單方法。當然還有很多方法,比如可以使用EF批量添加擴展,可以在EF中執行SQL插入語句,還可以用EF執行存儲過程的方式批量添加(SQL Server實驗過,MySql未實驗)等,大家還有啥好方法可以留言。日誌分析建議大家用mangodb或者ES等資料庫,本案例只是臨時數據分析。希望本文對你有所收穫,歡迎留言或者吐槽。
參考資料
來源公眾號:DotNet開發跳槽