SQL Server SqlBulkCopy 的使用,高效率批量插入數據。方法筆記,未測。sql
class SqlBulk { /// <summary> /// 向數據庫目標表中插入數據 /// </summary> /// <param name="sourceTable">源數據DataTable</param> /// <param name="connectStr">數據庫鏈接字符串</param> /// <param name="destinationTableName">數據庫中的目標表名</param> /// <returns>是否成功</returns> public bool SqlBulkInsert(DataTable sourceTable, string connectStr, string destinationTableName) { try { SqlConnection conn = new SqlConnection(connectStr); SqlBulkInsert(sourceTable, conn, destinationTableName); } catch (Exception e) { throw e; } finally { } return true; } /// <summary> /// 向數據庫目標表中插入數據 /// </summary> /// <typeparam name="T">源數據的基本數據類型</typeparam> /// <param name="sourceList">源數據列表</param> /// <param name="connectStr">數據庫鏈接字符串</param> /// <param name="destinationTableName">數據庫中的目標表名</param> /// <returns>是否成功</returns> public bool SqlBulkInsert<T>(List<T> sourceList, string connectStr, string destinationTableName) where T:new () { try { SqlConnection conn = new SqlConnection(connectStr); DataTable sourceTable=new DataTable(); sourceTable = ListToDataTable<T>(sourceList, sourceTable); SqlBulkInsert(sourceTable, conn, destinationTableName); } catch (Exception e) { throw e; } finally { } return true; } /// <summary> /// 向數據庫目標表中插入數據 /// </summary> /// <typeparam name="T">源數據的基本數據類型</typeparam> /// <param name="sourceList">源數據列表</param> /// <param name="conn">未打開的數據庫鏈接</param> /// <param name="destinationTableName">數據庫中的目標表名</param> /// <returns>是否成功</returns> public bool SqlBulkInsert<T>(List<T> sourceList, SqlConnection conn, string destinationTableName) where T:new () { try { DataTable sourceTable = new DataTable(); sourceTable = ListToDataTable<T>(sourceList, sourceTable); SqlBulkInsert(sourceTable, conn, destinationTableName); } catch (Exception e) { throw e; } finally { } return true; } /// <summary> /// 向數據庫目標表中插入數據 /// </summary> /// <param name="sourceTable">源數據DataTable</param> /// <param name="conn">未打開的數據庫鏈接</param> /// <param name="destinationTableName">數據庫中的目標表名</param> /// <returns>是否成功</returns> public bool SqlBulkInsert(DataTable sourceTable, SqlConnection conn, string destinationTableName) { DataSet ds = new DataSet(); using (SqlConnection _conn=new SqlConnection(conn.ConnectionString)) { _conn.Open(); SqlCommand cmd = new SqlCommand("SELECT TOP 0 * FROM " + destinationTableName, conn); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(ds); da.Dispose(); } foreach (DataColumn col in ds.Tables[0].Columns) { if (!sourceTable.Columns.Contains(col.ColumnName)) { throw new Exception("源數據表結構與目標表結構不對應"); } } SqlBulkCopy sbc = new SqlBulkCopy(conn); try { sbc.BulkCopyTimeout = 1800; sbc.DestinationTableName = destinationTableName; sbc.BatchSize = 1000; sbc.NotifyAfter = 1; sbc.SqlRowsCopied += new SqlRowsCopiedEventHandler(sbc_SqlRowsCopied); foreach (DataColumn col in ds.Tables[0].Columns) { sbc.ColumnMappings.Add(col.ColumnName, col.ColumnName); } conn.Open(); sbc.WriteToServer(sourceTable); sbc.Close(); } catch (Exception e) { throw e; } finally { sbc.Close(); conn.Close(); } return true; } void sbc_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) { //Console.WriteLine(e.RowsCopied + "rows are copierd"); } /// <summary> /// 根據目標數據表結構,將List中的數據儘可能填充到目標數據表 /// </summary> /// <typeparam name="T">數據類型</typeparam> /// <param name="list">數據列表</param> /// <param name="dt">數據表</param> /// <returns>返回數據表</returns> private DataTable ListToDataTable<T>(List<T> list, DataTable dt) where T : new() { dt.Clear(); foreach (var item in list) { DataRow dr = dt.NewRow(); foreach (var prop in typeof(T).GetProperties()) { if (dt.Columns.Contains(prop.Name)) { dr[prop.Name] = prop.GetValue(item, null); } } dt.Rows.Add(dr); } return dt; } }使用SqlBulkCopy類進行數據插入其原理是採用了SQL Server的BCP協議進行數據的批量複製。這裏咱們先要建好一個DataTable(最好是經過DataAdapter來灌數據獲得,由於這樣出來的DataTable就已經有跟數據表相同的列定義,能夠免去以後Mapping Column的步驟),把要插入的數據加進這個DataTable中,而後用SqlBulkCopy的實例來插入到數據庫中。通過測試,SqlBulkCopy方法比直接用Sql語句插入數據的效率高出將近25倍。 另外批量導入SQL、MYSQL等數據是一樣的for循環,使用拼出來的sql或者使用參數的方式傳遞或者使用事務等不一樣方式的傳遞效率都不一樣。若是不使用SqlBulkCopy的方式的話,我測試下來作快遞是用一次事務來操做爲最快。由於10000次的循環若是是每次提交,那麼都有連接和中止數據庫的操做,或者說他包含了1000次的小事務處理。若是外面就一個事務的話效率確定會高。