C#使用SqlTransaction事务回滚与SqlBulkCopy批量插入数据

C#中批量处理数据,有时候因为一条记录导致整个批量处理失败。这时候肯能会导致数据不全等问题,这时候我们可以使用SqlTransaction来进行事务回滚,即是要么全部成功要么全部不成功。如下代码

  //测试事务回滚
        public static string GetMsgBySJ()
        {
            var msg = "";
            SqlConnection conn = new SqlConnection(connStr);
            SqlCommand cmd = conn.CreateCommand();
            conn.Open();//打开之后开启事务
            SqlTransaction tran = conn.BeginTransaction();//开启事务
            cmd.Transaction = tran;//将事务应用于CMD
            try
            {
                cmd.CommandText = " INSERT into t_student VALUES ('huage1','11','男神') ";
                cmd.ExecuteNonQuery();
                cmd.CommandText = " INSERT into t_student VALUES ('huage','11','女神','') ";
                cmd.ExecuteNonQuery();
                tran.Commit();//提交事务(不提交不会回滚错误)
                msg = "插入成功";
            }
            catch (Exception ex)
            {
                tran.Rollback();
                msg = "插入失败,事物回滚";
            }
            finally
            {
                conn.Close();
                conn.Dispose();
                cmd.Dispose();
                tran.Dispose();
            }
            return msg;
        }

上面测试代码,INSERT into t_student VALUES ('huage1','11','男神')这条记录其实已经插入数据库,但是因为下条语句操作失败导致插入数据错误,这时候这个Rollback()函数会将数据库表中的数据还原到操作表之前,

也就是说第一条执行成功的语句也会被删掉(如果有自增Id的话,可以去数据库中再插入数据查看Id是否不再连续)。

  下面在介绍一个SqlBulkCopy批量快速插入数据的方法,如果数据量大的话用循环语句进行数据的插入那肯定会使程序变的巨慢,这时候使用SqlBulkCopy来进行插入数据的话就会显得很优越

下面以插入10000行数据做测试。

 //批量将数据导入目的表
        public static void DtDrTable(DataTable dt, string tableName)
        {
            try
            {
                //这边可以使用事务回滚机制
                SqlBulkCopy bcp = new SqlBulkCopy(connStr);
                //指定目标数据库的表名
                bcp.DestinationTableName = tableName;
                //每一批次的行数
                bcp.BatchSize = 100 * 100;
                //建立数据源表字段和目标表中的列之间的映射
                //----既然dt的列名需要与表明完全一致,直接循环dt的列即可----//
                foreach (DataColumn dc in dt.Columns)
                    bcp.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
                //写入数据库表 dt 是数据源DataTable
                bcp.WriteToServer(dt);
                //关闭SqlBulkCopy实例
                bcp.Close();
            }
            catch (Exception ex)
            {                
                throw ex;
            }
        }

使用SqlBulkCopy进行数据插入的时候,要使得DataTable中的列名,类型与数据库表要完全一致(除了自增Id),下面是调用上面方法的例子

 Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            DataTable dtTemp = new DataTable();
            DataColumn[] columns = new DataColumn[]
            {
             new DataColumn("Name",typeof(string)),
             new DataColumn("Age",typeof(Int32)),
             new DataColumn("Sex",typeof(string)),
             new DataColumn("test",typeof(string)),
            };
            dtTemp.Columns.AddRange(columns);
            //构造一个10000行的DataTable
            for (var i = 0; i < 100 * 100; i++)
            {
                var n_row = dtTemp.NewRow();
                var tt = i + 1;
                n_row["Name"] = "Name" + tt;
                n_row["Age"] = tt;
                n_row["Sex"] = "Sex" + tt;
                n_row["test"] = "test" + tt;
                dtTemp.Rows.Add(n_row);
            }
            stopWatch.Stop();
            Console.WriteLine("构造一万行的Datatable所需时间:" + stopWatch.Elapsed);

            Stopwatch stopwatcj = new Stopwatch();
            stopwatcj.Start();
            DtDrTable(dtTemp, "t_student");
            stopwatcj.Stop();
            Console.WriteLine("10000行数据批量插入表中所需时间:" + stopwatcj.Elapsed);

执行上述测试代码的控制台程序,结果如下:

 

甚至一秒时间都没到,在内存中构建内存表虽然更快,但是很费内存

  下面展示一个可回滚的批量插入(暂时未测试)

 

        //批量将数据导入目的表可回滚
        public static void TranBatchImportData(DataTable dt, string tableName)
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();
                SqlTransaction tran = conn.BeginTransaction();
                using (SqlBulkCopy sqlBC = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, tran))
                {
                    sqlBC.BatchSize = 100 * 100;
                    //sqlBC.BulkCopyTimeout = 60;//超时之前操作完成所允许的秒数
                    sqlBC.DestinationTableName = tableName;
                    foreach (DataColumn dc in dt.Columns)
                        sqlBC.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);

                    sqlBC.WriteToServer(dt);
                    tran.Commit();
                }
            }
        }

 

转载于:https://www.cnblogs.com/huage-1234/p/8079146.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值