• 批量插入数据利器之SqlBulkCopy


    工作中要频繁的处理一些数据导入,又不想手工去做,因此用了神器SqlBulkCopy。在MSDN查看了此类的帮助文档几经波折终于搞定,记录下来方便以后查阅。

    MSDN实例:

     1 using System.Data.SqlClient;
     2 
     3 class Program
     4 {
     5     static void Main()
     6     {
     7         string connectionString = GetConnectionString();
     8         // Open a sourceConnection to the AdventureWorks database.
     9         using (SqlConnection sourceConnection =
    10                    new SqlConnection(connectionString))
    11         {
    12             sourceConnection.Open();
    13 
    14             // Perform an initial count on the destination table.
    15             SqlCommand commandRowCount = new SqlCommand(
    16                 "SELECT COUNT(*) FROM " +
    17                 "dbo.BulkCopyDemoMatchingColumns;",
    18                 sourceConnection);
    19             long countStart = System.Convert.ToInt32(
    20                 commandRowCount.ExecuteScalar());
    21             Console.WriteLine("Starting row count = {0}", countStart);
    22 
    23             // Get data from the source table as a SqlDataReader.
    24             SqlCommand commandSourceData = new SqlCommand(
    25                 "SELECT ProductID, Name, " +
    26                 "ProductNumber " +
    27                 "FROM Production.Product;", sourceConnection);
    28             SqlDataReader reader =
    29                 commandSourceData.ExecuteReader();
    30 
    31             // Open the destination connection. In the real world you would 
    32             // not use SqlBulkCopy to move data from one table to the other 
    33             // in the same database. This is for demonstration purposes only.
    34             using (SqlConnection destinationConnection =
    35                        new SqlConnection(connectionString))
    36             {
    37                 destinationConnection.Open();
    38 
    39                 // Set up the bulk copy object. 
    40                 // Note that the column positions in the source
    41                 // data reader match the column positions in 
    42                 // the destination table so there is no need to
    43                 // map columns.
    44                 using (SqlBulkCopy bulkCopy =
    45                            new SqlBulkCopy(destinationConnection))
    46                 {
    47                     bulkCopy.DestinationTableName =
    48                         "dbo.BulkCopyDemoMatchingColumns";
    49 
    50                     try
    51                     {
    52                         // Write from the source to the destination.
    53                         bulkCopy.WriteToServer(reader);
    54                     }
    55                     catch (Exception ex)
    56                     {
    57                         Console.WriteLine(ex.Message);
    58                     }
    59                     finally
    60                     {
    61                         // Close the SqlDataReader. The SqlBulkCopy
    62                         // object is automatically closed at the end
    63                         // of the using block.
    64                         reader.Close();
    65                     }
    66                 }
    67 
    68                 // Perform a final count on the destination 
    69                 // table to see how many rows were added.
    70                 long countEnd = System.Convert.ToInt32(
    71                     commandRowCount.ExecuteScalar());
    72                 Console.WriteLine("Ending row count = {0}", countEnd);
    73                 Console.WriteLine("{0} rows were added.", countEnd - countStart);
    74                 Console.WriteLine("Press Enter to finish.");
    75                 Console.ReadLine();
    76             }
    77         }
    78     }
    79 
    80     private static string GetConnectionString()
    81         // To avoid storing the sourceConnection string in your code, 
    82         // you can retrieve it from a configuration file. 
    83     {
    84         return "Data Source=(local); " +
    85             " Integrated Security=true;" +
    86             "Initial Catalog=AdventureWorks;";
    87     }
    88 }

    MSDN 地址:https://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx

    自己的测试代码:

     1 /// <summary>
     2         /// 将DataTable表数据插入数据库目标表
     3         /// DataTable Name 和数据库目标表名称一致,DataTable列名为目标数据库目标表字段
     4         /// </summary>
     5         /// <param name="dt">数据源</param>
     6         /// <param name="dbFlag">数据库标识</param>
     7         /// <returns></returns>
     8         public static bool MassInsert(DataTable dt, string dbFlag)
     9         {
    10             if (dt == null || dt.Rows.Count == 0)
    11             {
    12                 Logger.Write("DataTable为空或无填充行", "大数据操作", "");
    13                 return false;
    14             }
    15             if (String.IsNullOrEmpty(dt.TableName))
    16             {
    17                 Logger.Write("DataTableName为空无法确定目标数据库表", "大数据操作", "");
    18                 return false;
    19             }
    20             SqlConnection con = HelpGetSqlCon(dbFlag);//动态获取SqlConnection对象
    21             DateTime time = DateTime.Now;
    22             SqlTransaction tra = con.BeginTransaction();//事务
    23             SqlBulkCopy sqlBC = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, tra);
    24             try
    25             {
    26                 sqlBC.DestinationTableName = dt.TableName;
    27                 //一次批量的插入的数据量
    28                 sqlBC.BatchSize = dt.Rows.Count;
    29                 sqlBC.WriteToServer(dt);
    30                 Logger.Write("【MassInsert】[" + dt.Rows.Count + "]条数据共耗时[" + (DateTime.Now - time).TotalSeconds.ToString() + "]秒", "", ""); //记录日志
    31                 tra.Commit();
    32                 return true;
    33             }
    34             catch (Exception ex)
    35             {
    36                 tra.Rollback();
    37                 Logger.WriteException("MassInsert异常", "", ex, "");
    38                 return false;
    39             }
    40             finally
    41             {
    42                 dt.Clear();
    43                 dt.Dispose();
    44                 sqlBC.Close();
    45                 con.Dispose();
    46                 con.Close();
    47             }
    48         }

    以上代码可以插入主键,如果主键重复则事务回滚

    正常测试结果:

    【2015-04-29 12:49:44】
    【MassInsert】[182689]条数据共耗时[3.4911996]秒

    主键重复测试结果:

    【2015-04-29 12:41:16】

    Message:MassInsert异常

    Ex.Message:违反了 PRIMARY KEY 约束“PK_AUTHCODES”。不能在对象“dbo.AuthCodes”中插入重复键。重复键值为 (1)。
    语句已终止。

    Ex.StackTrace: 在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
    在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
    在 System.Data.SqlClient.SqlBulkCopy.RunParser(BulkCopySimpleResultSet bulkCopyHandler)
    在 System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinuedOnSuccess(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
    在 System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
    在 System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
    在 System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
    在 System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
    在 System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
    在 System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
    在 System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
    在 System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table)

  • 相关阅读:
    使用Python来临时启动端口,用来做安全时候的扫描用
    awk工作流程
    AWK的内置变量
    类型定义VS类型别名
    定义函数只能使用本地当前包中的类型,不能使用其他包中的类型
    命名类型和未命名类型和基础类型
    类型字面值
    type switch使用
    "指针"和"引用"大对比
    预测球队比赛成绩
  • 原文地址:https://www.cnblogs.com/yf2011/p/4465687.html
Copyright © 2020-2023  润新知