文章出處
文章列表
對于大數據量提交,包括插入,更新和刪除,我始終不建議用EF自帶的方法,因為它會增加與數據庫的交互次數,一般地,EF的一個上下文在提交時會打開一個數據連接,然后把轉換成的SQL語句一條一條的發到數據庫端,然后去提交,試想,如果你的數據量達到萬級別(更不用說百萬,千萬數據了),那對數據庫的壓力是很大的,所以,我將EF批量操作語句進行了改版,并起名為BulkInsert,BulkUpdate和BulkDelete,事實上,在我之前的版本中并沒有涉及到批次提交的概念,直到遇到了實際的問題,當你使用BulkInsert時,如果數據達到4萬之前,那在SQL的解釋時,也是很有壓力的,有多情況下會超時,當然這與你的數據庫服務器有關,但為了性能與安全,我還是決定將Bulk操作變為分批提交,即將4W進行分解,分用1W數據量提交一次,這樣,對數據庫的壓力就小一些。看看我的改版吧。
public void BulkInsert(IEnumerable<TEntity> item) { DataPageProcess(item, (currentItems) => { ((IObjectContextAdapter)_Db).ObjectContext.CommandTimeout = 0;//永不超時 _Db.Database.ExecuteSqlCommand(DoSQL(currentItems, SQLType.Insert)); }); } public void BulkDelete(IEnumerable<TEntity> item) { DataPageProcess(item, (currentItems) => { ((IObjectContextAdapter)_Db).ObjectContext.CommandTimeout = 0;//永不超時 _Db.Database.ExecuteSqlCommand(DoSQL(currentItems, SQLType.Delete)); }); } public void BulkUpdate(IEnumerable<TEntity> item) { DataPageProcess(item, (currentItems) => { ((IObjectContextAdapter)_Db).ObjectContext.CommandTimeout = 0;//永不超時 _Db.Database.ExecuteSqlCommand(DoSQL(currentItems, SQLType.Update)); }); }
/// <summary> /// 分頁進行數據提交的邏輯 /// </summary> /// <param name="item">原列表</param> /// <param name="method">處理方法</param> /// <param name="currentItem">要進行處理的新列表</param> private void DataPageProcess(IEnumerable<TEntity> item, Action<IEnumerable<TEntity>> method) { if (item != null && item.Count() > 0) { DataTotalCount = item.Count(); this.DataTotalPages = item.Count() / DataPageSize; if (DataTotalCount % DataPageSize > 0) DataTotalPages += 1; for (int pageIndex = 1; pageIndex <= DataTotalPages; pageIndex++) { var currentItems = item.Skip((pageIndex - 1) * DataPageSize).Take(DataPageSize).ToList(); method(currentItems); } } }
我們可以看到,改版后的方法,沒有直接把集合item傳遞給方法ExecuteSqlCommand去執行,而去調用了一個方法,這個方法然后傳入一個委托,然這個委托的
輸入參數是一個分頁的數據集合,這時你的ExecuteSqlCommand方法接入的集合參數將是一個分了頁之后的小集合,呵呵。
對于一次提交的數量,你可以在類中去定義,它類似于分頁,所以,我通常叫這個方法為數據分頁提交!
#region Fields /// <summary> /// 數據總數 /// </summary> int DataTotalCount = 0; /// <summary> /// 數據總頁數 /// </summary> int DataTotalPages = 0; /// <summary> /// 數據頁面大小(每次向數據庫提交的記錄數) /// </summary> int DataPageSize = 10000; #endregion
如果你希望得到BlukInsert的完整方法,請關注本人的EF架構系列
文章列表
全站熱搜