意外發現的大批量導入數據SqlBulkCopy類


因為要做一個號碼歸屬地查詢小功能,因為要導入外部(文本文件)的電話歸屬地數據,使用的是SqlDataAdapter類,數據不多,只四萬有多條,表也只有一個,phoneBook表,使用的是DataTable和SqlDataAdapter,測試了三次導入,平均18秒,但是我覺得太慢了,就百度了下【SQL Server批量導入數據】,發現了SqlBulkCopy這個神器,一秒內導入。

      SqlBulkCopy 這個類用於數據庫大批量的數據傳遞,通常用於新舊數據庫之間的更新。關鍵的一點是,即使表結構不同,也可以通過表字段或者字段位置建立映射關系,將所需的數據導入到目標數據庫。

下面代碼測試了數據量為一百萬條數據,幾次測試耗時8秒左右。

/// <summary>
        /// SqlBulkCopy類的使用,批量更新數據
        /// </summary>
        public static void SqlBulkCopyDemo()
        {
            String connStr = ConfigurationManager.ConnectionStrings["connStr"].ToString();
            //從數據庫中獲得表結構和數據
            DataTable student = new DataTable();
            SqlDataAdapter adapter = new SqlDataAdapter("select * from student", connStr);
            adapter.Fill(student);
            //向表中添加數據
            DataRow dr;
            Random r = new Random();
            Stopwatch st = new Stopwatch();
            for(int i = 0; i<1000000; i++)//一百萬條數據
            {//數據表中的列:name,no,age,sex
                dr = student.NewRow();
                dr[0] = "小花" + i;
                dr[1] = 108 + i;
                dr[2] = r.Next(9, 40);//這里是因為數據表中有約束,
                dr[3] = (i % 2 == 0 ? "" : "");//這個也是有約束
                student.Rows.Add(dr);
            }
            SqlBulkCopy bulk = new SqlBulkCopy(connStr);
            bulk.DestinationTableName = "student";//設置目標表,這里是數據庫中的student表
            bulk.ColumnMappings.Add(0, 0);//建立映射關系
            bulk.ColumnMappings.Add(1, 1);
            bulk.ColumnMappings.Add(2, 2);
            bulk.ColumnMappings.Add(3, 3);
            st.Start();//開始計時
            bulk.WriteToServer(student.GetChanges());
            st.Stop();//結束計時
            Console.WriteLine("數據插入成功,耗時為:" + st.ElapsedMilliseconds + "毫秒");
        }

測試了三次,結果如下:

5

6

7

 

1、SqlBulkCopy類的構造方法

其中: conn表示一個SqlConnection對象

         connStr表示數據庫連接字符串

  1. SqlBulkCopy(conn)
  2. SqlBulkCopy(connStr)
  3. SqlBulkCopy(connStr, SqlBulkCopyOptions copyOptions)
  4. SqlBulkCopy(conn, SqlBulkCopyOptions copyOptions, SqlTransaction externalTransaction)

其中還有幾個陌生的對象:SqlBulkCopyOptions 和 SqlTransaction

1.1、SqlBulkCopyOptions類

這個類是一個枚舉類型:

對象 備注
Default 0  
KeepIdentity 1 保留源標識值。
如果未指定,則由目標分配標識值。
CheckConstraints 2 在插入數據的同時檢查約束。
默認情況下,不檢查約束。
TableLock 4 在批量復制操作期間獲取批量更新鎖。
如果未指定,則使用行鎖。
KeepNulls 8 保留目標表中的空值,而不管默認值的設置如何。
如果未指定,則空值將由默認值替換(如果適用)
FireTriggers 16 指定后,會導致服務器為插入到數據庫中的行激發插入觸發器。
UseInternalTransaction 32

如果已指定,則每一批批量復制操作將在事務中進行。

如果指示了此選項,並且為構造函數提供了 System.Data.SqlClient.SqlTransaction對象,則發生 System.ArgumentException(參數異常)。因為兩個事務沖突了。

1.2、SqlTransaction類

這個類是事務類,是個密封類,實現了DbTransaction抽象類

 

 

 

2、SqlBulkCopy類的常用屬性

屬性名 功能 備注
BatchSize 設置或獲取每達到多少行就更新到服務器(也就是目標表) 值為int,
BulkCopyTimeout 設置或獲取超時時間 默認30秒,如果設置成0,將無限制等待,
值為int,單位為秒
DestinationTableName 設置或獲取服務器上的目標表的名稱 也就是批量更新的目標表,
值為String類型
EnableStreaming 設置或獲取是否支持傳輸 IDataReader 對象的數據 true為支持,
值為bool類型
NotifyAfter 設置或獲取在生成通知事件之前要處理的行數 默認為0,
值為int類型,
ColumnMappings 獲取列映射定義數據源中的列和目標表中的列之間的映射關系 返回值為SqlBulkCopyColumnMappingCollection

2.1、表中的SqlBulkCopyColumnMappingCollection類型是一個映射集合類,是目標表的列和源表的列的映射關系的集合。

這個類是一個密封類,不能被繼承,實現了一個CollectionBase抽象類。

SqlBulkCopyColumnMappingCollection沒有提供構造方法,我們也不需要去newat的對象,主要是使用它的幾個重載的Add()方法

Add()有五個重載的方法:

  • SqlBulkCopyColumnMapping Add(SqlBulkCopyColumnMapping bulkCopyColumnMapping);
  • SqlBulkCopyColumnMapping Add(string sourceColumn, string destinationColumn);
  • SqlBulkCopyColumnMapping Add(int sourceColumnIndex, string destinationColumn);
  • SqlBulkCopyColumnMapping Add(string sourceColumn, int destinationColumnIndex);
  • SqlBulkCopyColumnMapping Add(int sourceColumnIndex, int destinationColumnIndex);

其中四個方法是類似的,都是對應的列名或者列的位置

第一個方法是添加一個已經構建好的SqlBulkCopyColumnMapping對象,

他也有集合常用的方法:

    方法名 功能 備注
    Clear(); 清除集合中的映射關系  
    Contains(SqlBulkCopyColumnMapping value); 判斷是否包含指定映射關系  
    IndexOf(SqlBulkCopyColumnMapping value); 返回指定映射關系的位置  
    Remove(SqlBulkCopyColumnMapping value); 移除指定映射關系  
    RemoveAt(int index); 移除指定位置的映射關系  
    Insert(int index, SqlBulkCopyColumnMapping value); 在指定位置插入映射關系  
    CopyTo(SqlBulkCopyColumnMapping[] array, int index); 從指定位置開始將映射關系復制到指定數組中 index指定的集合中的位置,
    而不是數組中的角標

 

3、SqlBulkCopy類的常用方法

  • WriteToServer,這個方法重載了四次,功能是將數據寫到目的表中。
WriteToServer(DataRow[] rows); 將 DataRow 數組所有元素寫到目標表中
WriteToServer(DataTable table); 將 DataTable 所有行寫到目標表中
WriteToServer(IDataReader reader); 將指定的 IDataReader 對象中的數據寫到目標表中
WriteToServer(DataTable table, DataRowState rowState); 將 DataTable 中指定狀態的所有行寫到目標表中

【上表中的 DataRowState 狀態行可以參考這篇博客DataTable的AcceptChanges()方法和DataRow的RowState屬性

這個類還提供了八個異步寫的方法,我還沒全部理解,就不放上來了。

既然能夠有寫的操作,那這個類應該類似於流,它還有一個Close()方法,用於關閉 SqlBulkCopy 實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM