使用事務操做SQLite數據批量插入,提升數據批量寫入速度,源碼講解

SQLite數據庫做爲通常單機版軟件的數據庫,是很是優秀的,我目前單機版的軟件產品線基本上所有替換Access做爲優選的數據庫了,在開發過程當中,有時候須要批量寫入數據的狀況,發現傳統的插入數據模式很是慢,幾千條數據的寫入或者更新可能須要好幾分鐘時間,而SqlServer則相同的操做可能幾秒便可,有無更好的方法來提升它的響應速度呢?答案是有的,就是採用事務提交,默認SQLite的數據庫插入操做,若是沒有采用事務的話,它每次寫入提交,就會觸發一次事務操做,而這樣幾千條的數據,就會觸發幾千個事務的操做,這就是時間耗費的根源。本文經過詳細代碼介紹如何使用事務來提升整個批量插入數據的速度,並以實際的Winform開發框架中的字典管理模塊的批量插入功能來進行介紹,經過先後速度的對比,使得事務操做提升響應速度更有說服力。數據庫

因爲一些項目須要,字典管理模塊須要批量錄入數據,所以改善了個人《Winform開發框架》中的字典管理模塊,在字典管理模塊增長一個批量添加的功能,以下所示。框架

對一些診斷的數據錄入,通常狀況下均可能是幾千條的數據,還有可能更多的一些分類字典,那麼若是每次都須要等待幾分鐘或者幾十分鐘,那麼這樣的響應體驗確定不好。函數

爲了提升響應速度,我這裏使用了事務操做,整個事務操做是基於EnterpriseLibray類庫的數據庫操做,因爲我已經在框架的基類中作了封裝,所以咱們這裏看到整個處理過程便可。測試

其中MyRegion裏面的代碼就是遍歷每行的數據,構造數據字典對象和排序號,而後調用InsertDictData函數進行數據的錄入。其中InsertDictData函數的代碼是this

        /// <summary>
        /// 使用事務參數,插入數據,最後統一提交事務處理
        /// </summary>
        /// <param name="dictData">字典數據</param>
        /// <param name="seq">排序</param>
        /// <param name="trans">事務對象</param>
        private void InsertDictData(string dictData, string seq, DbTransaction trans)
        {
            if (!string.IsNullOrWhiteSpace(dictData))
            {
                DictDataInfo info = new DictDataInfo();
                info.Editor = LoginID;
                info.LastUpdated = DateTime.Now;
                info.DictType_ID = this.txtDictType.Tag.ToString();
                info.Name = dictData.Trim();
                info.Value = dictData.Trim();
                info.Remark = this.txtNote.Text.Trim();
                info.Seq = seq;

                bool succeed = BLLFactory<DictData>.Instance.Insert(info, trans);
            }
        }

整個插入功能按鈕的處理所有代碼以下所示。spa

        private void btnOK_Click(object sender, EventArgs e)
        {
            string[] arrayItems = this.txtDictData.Lines;
            int intSeq = -1;
            int seqLength = 3;
            string strSeq = this.txtSeq.Text.Trim();
            if (int.TryParse(strSeq, out intSeq))
            {
                seqLength = strSeq.Length;
            }

            if (arrayItems != null && arrayItems.Length > 0)
            {
                DbTransaction trans = BLLFactory<DictData>.Instance.CreateTransaction();
                if (trans != null)
                {
                    try
                    {
                        #region MyRegion
                        foreach (string strItem in arrayItems)
                        {
                            if (this.radSplit.Checked)
                            {
                                if (!string.IsNullOrWhiteSpace(strItem))
                                {
                                    string[] dataItems = strItem.Split(new char[] { ',', '', ';', '', '/', '' });
                                    foreach (string dictData in dataItems)
                                    {
                                        #region 保存數據
                                        string seq = "";
                                        if (intSeq > 0)
                                        {
                                            seq = (intSeq++).ToString().PadLeft(seqLength, '0');
                                        }
                                        else
                                        {
                                            seq = string.Format("{0}{1}", strSeq, intSeq++);
                                        }

                                        InsertDictData(dictData, seq, trans); #endregion
                                    }
                                }
                            }
                            else
                            {
                                #region 保存數據
                                if (!string.IsNullOrWhiteSpace(strItem))
                                {
                                    string seq = "";
                                    if (intSeq > 0)
                                    {
                                        seq = (intSeq++).ToString().PadLeft(seqLength, '0');
                                    }
                                    else
                                    {
                                        seq = string.Format("{0}{1}", strSeq, intSeq++);
                                    }

                                    InsertDictData(strItem, seq, trans);
                                }
                                #endregion
                            }
                        }
                        #endregion

                        trans.Commit();
                        ProcessDataSaved(this.btnOK, new EventArgs());
                        MessageDxUtil.ShowTips("保存成功");
                        this.DialogResult = DialogResult.OK;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        LogTextHelper.Error(ex);
                        MessageDxUtil.ShowError(ex.Message);
                    }
                }
            }
        }

上面的批量插入,通過先後的測試,2千條數據批量插入SQLite數據庫,須要大概3~4分鐘左右,若是採用了事務操做,則在1~2秒內寫入完成,速度提升不知道多少倍。若是是操做數據比較多的,強烈建議使用事務進行操做,能夠給客戶很好的體驗效果。code

若是嫌上面的代碼複雜,能夠看下面的講解代碼可能就明白了orm

        using (DbTransaction dbTrans = conn.BeginTransaction())
        {
            using (DbCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = "INSERT INTO MyTable(MyValue) VALUES(?)";
                DbParameter Field1 = cmd.CreateParameter();
                cmd.Parameters.Add(Field1);
                for (int n = 0; n < 100000; n++)
                {
                    Field1.Value = n + 100000;
                    cmd.ExecuteNonQuery();
                }
            }
        }

上面是一種比較簡單原始的事務操做,若是批量插入數據,一樣可以起到同樣的效果。對象

相關文章
相關標籤/搜索