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次的小事务处理。若是外面就一个事务的话效率确定会高。