文章出處

回到目錄

對于大數據量提交,包括插入,更新和刪除,我始終不建議用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架構系列

回到目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()