SqlBulkCopy  做为SQL Server 官方 批量入库类,性能不会太差。其事务部份官方说明较模糊,因此 针对事务配置做了一些测试。

  A. 先准备测试场景 ,关于SqlBulkCopyOptions.KeepIdentity 应用。  新建两张表 , 每张表列a 做为自增列,同时做为主键 , 其中 test_sqlbulk 源表 ,先添加一组数据。

CREATE TABLE [dbo].[test_sqlbulk](
[a] [int] IDENTITY(1,1) NOT NULL,
[b] [int] NULL,
CONSTRAINT [PK_test_sqlbulk] PRIMARY KEY CLUSTERED
(
[a] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] CREATE TABLE [dbo].[test_sqlbulk_des](
[a] [int] IDENTITY(1,1) NOT NULL,
[b] [int] NULL,
CONSTRAINT [PK_test_sqlbulk_des] PRIMARY KEY CLUSTERED
(
[a] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

添加数据:

测试代码:

 SqlConnection sqlConn = new SqlConnection( sourceConnection) ;
sqlConn.Open() ;
SqlCommand commandSourceData = new SqlCommand("select * from test_sqlbulk ", sqlConn);
SqlDataReader reader = commandSourceData.ExecuteReader(); // Set up the bulk copy object using the KeepIdentity option.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
sourceConnection))
{
bulkCopy.BatchSize = ;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}

再看看目标表 test_sqlbulk_des 结果 , 由于SqlBulkCopy  构造参数没有 KeepIdentity 标识,目标表自增列与源表不一致 :

test_sqlbulk_des 查询结果:

=>调整代码,增加 SqlBulkCopyOptions.KeepIdentity 选项,再次导入:

 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
sourceConnection, SqlBulkCopyOptions.KeepIdentity))
{
bulkCopy.BatchSize = 2;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}

=>目标表,源表自增列一致了:

B. 测试无事务,内部事务(SqlBulkCopyOptions.UseInternalTransaction) , 外部传入事务 之间区别 , 以下所有测试均事先在目标表保留一行数据 使copy 过程中造成主键冲突,查看回退情况。

1. 无事务测试。初使化源表,目标表数据:

测试代码 , 不意外,如下代码最终会产生主键冲突错误, 执行结束后,再查询源表,目标表数据 。 BatchSize 设置为2 , 结果表明在第二批次主键冲突, 第一批次数据成功提交了(没有显示声明事务), 再将 BatchSize 设置为3 验证结果。

 SqlConnection sqlConn = new SqlConnection( sourceConnection) ;
sqlConn.Open() ;
SqlCommand commandSourceData = new SqlCommand("select * from test_sqlbulk ", sqlConn);
SqlDataReader reader = commandSourceData.ExecuteReader(); // Set up the bulk copy object using the KeepIdentity option.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
sourceConnection, SqlBulkCopyOptions.KeepIdentity))
{
bulkCopy.BatchSize = 2;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}

BatchSize = 2 结果:

BatchSize = 3 结果:

2.指定内部事务 , 分别将 BatchSize 指定为 2 , 3, 4  。如下执行结果与上文示例 结果一致, 因此无论是否指定 SqlBulkCopyOptions.UseInternalTransaction 参数(不包括外部传入事务) ,SqlBulkCopy 内部按照一个批次一个事务。在出现异常时只回滚当前批次 , 在此之前成功执行批次不回滚。 因此若需全部回退,需将  BatchSize 设为 总记录条数 ,此时所有数据做为一个批次提交 ,  异常回退批次,回退数据范围即全部数据。

测试代码:

 // Set up the bulk copy object using the KeepIdentity option.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
sourceConnection, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
{
bulkCopy.BatchSize = 2;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}

=>BatchSize = 2  , 目标表结果:

=>BatchSize = 3  , 目标表结果:

3. 外部传入事务对象场景 , 如果 使用SqlBulkCopy入库操作只做为本次业务处理一个子集,在整个业务处理环节中异常情况,需要回滚整个业务操作。 本次再新建一张表:test_sqlbulk_update , 测试过程中,先对该表增加一条记录,再重复之前异常场景。 结束时,之前新增记录也回退了。

因此, 当外部传入事务对象时,SqlBulkCopy  内部不提交事务, 在异常情况,有可能会自动回滚。

CREATE TABLE [dbo].[test_sqlbulk_update](
[a] [int] IDENTITY(1,1) NOT NULL,
[b] [int] NULL,
)
SqlConnection sqlConn = new SqlConnection( sourceConnection) ;
sqlConn.Open() ; SqlTransaction tran = sqlConn.BeginTransaction(); SqlCommand commandInsert = new SqlCommand("insert into [test_sqlbulk_update]( b ) values (1) ", sqlConn, tran); int result = commandInsert.ExecuteNonQuery(); SqlCommand commandSourceData = new SqlCommand("select * from test_sqlbulk ", sqlConn, tran); SqlDataReader reader = commandSourceData.ExecuteReader(); // Set up the bulk copy object using the KeepIdentity option.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.KeepIdentity, tran))
{
bulkCopy.BatchSize = 2;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{
bulkCopy.WriteToServer(reader);
reader.Close();
tran.Commit();
}
catch (Exception ex)
{
reader.Close();
tran.Rollback();
            // tran.Commit(); 异常仍提交执行,同时注释上一行。
} }

=> 异常时执行 rollback, 最终结果:没做任何修改.

=> 外部事务,Catch 中执行 Commint ,发生异常,因为自动回滚了,但在Catch 执行 Rollback 无异常。

SqlTransaction tran = sqlConn.BeginTransaction();

            SqlCommand commandSourceData = new SqlCommand("select * from test_sqlbulk ", new SqlConnection(sourceConnection));

            SqlDataAdapter ada = new SqlDataAdapter(commandSourceData ) ;
System.Data.DataSet ds = new System.Data.DataSet();
ada.Fill(ds); // Set up the bulk copy object using the KeepIdentity option.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.KeepIdentity, tran))
{
bulkCopy.BatchSize = ;
bulkCopy.DestinationTableName =
"dbo.test_sqlbulk_des"; // Write from the source to the destination.
// This should fail with a duplicate key error
// after some of the batches have been copied.
try
{ bulkCopy.WriteToServer(ds.Tables[]); SqlCommand commandInsert = new SqlCommand("insert into [test_sqlbulk_update]( b ) values ('a') ", sqlConn, tran); int result = commandInsert.ExecuteNonQuery(); tran.Commit();
}
catch (Exception ex)
{
tran.Commit();
} }

SqlBulkCopy 参数配置示例的更多相关文章

  1. Hystrix参数配置

    1.Hystrix参数配置文档  2.Hystrix参数配置示例 import org.springframework.beans.factory.annotation.Autowired; impo ...

  2. 教你如何利用分布式的思想处理集群的参数配置信息——spring的configurer妙用

    引言 最近LZ的技术博文数量直线下降,实在是非常抱歉,之前LZ曾信誓旦旦的说一定要把<深入理解计算机系统>写完,现在看来,LZ似乎是在打自己脸了.尽管LZ内心一直没放弃,但从现状来看,需要 ...

  3. HBase + Kerberos 配置示例(二)

    接上篇<HBase + Kerberos配置示例(一)>,我们继续剩下的配置工作. 环境准备 Hadoop配置 Zookeeper配置 HBase配置 Java测试程序 环境准备 安装ha ...

  4. Linux环境下vsftpd参数配置

    很久之前就用过vsftpd,但总是忘了参数该如何配置,今天特地有搜索了一遍,把配置方法整理如下: (1)检查是否已安装vsftpd #rpm -qa | grep vsftpd vsftpd--.el ...

  5. Haproxy的安装和配置示例

    1.ha proxy简介ha proxy是一个开源的,高性能的,基于tcp第四层和http第七层应用的负载均衡软件优点:可靠性和稳定性非常好          最高可以同时维护40000-50000个 ...

  6. java日志规约及配置示例终极总结

    目录 什么是日志 常用日志框架 日志级别详解 日志的记录时机 日志使用规约 logback 配置示例 loh4j2 配置示例 什么是日志? 简单的说,日志就是记录程序的运行轨迹,方便查找关键信息,也方 ...

  7. spring boot 日志介绍 以及 logback配置示例

    https://www.cnblogs.com/flying607/p/7827460.html 以下是springboot的一个局部依赖关系: 可以看到,java util logging(jul) ...

  8. Mysql半同步复制模式说明及配置示例 - 运维小结

    MySQL主从复制包括异步模式.半同步模式.GTID模式以及多源复制模式,默认是异步模式 (如之前详细介绍的mysql主从复制).所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二 ...

  9. HAPRoxy(一):HAProxy基本配置、调度算法与tcp、http、heath模式配置示例

    一.HAProxy安装 1.HAProxy简单介绍 HAProxy虽然名字前有HA,但它并不是一款高可用软件,而是一款用于实现负载均衡的软件,可实现四层与七层的负载均衡. 2.yum安装HAProxy ...

随机推荐

  1. Python random模块(获取随机数)

    1.random.random 随机生成一个0到1的随机浮点数: 0 <= n < 1.0 In [2]: print random.random() 0.544824016934 2.r ...

  2. 【good】在CentOS 6.x上安装GlusterFS

    转发:http://quenywell.com/install-glusterfs-on-centos-6-x/ 本文主要介绍如何在CentOS 6.x上快速安装GlusterFS.GlusterFS ...

  3. sass和compass实战 读书笔记(一)

    sass优势: 不做重复的工作 一  消除样式表冗余(通过变量赋值的方式) 1. 通过变量来复用属性值 2. 使用嵌套来快速写出多层级的选择器 3. 通过混合器来复用一段样式 4. 使用选择器继承来避 ...

  4. web项目各个clean

    project clean:清楚tomcat下的已编译的java类.class文件,包括js但不包括jsp server clean:clean tomcat work dictionary:清除to ...

  5. POI--HSSFSheet类

    用POI来作成一个Sheet,可以用「HSSFSheet」类,该类构造器如下: 新建Sheet 从构造器可以看出,虽然它有两个构建器,但都是protected的,所以要新建Sheet,只能通过Work ...

  6. WPF笔记(2.4 Grid)

    第一章已经简单介绍过这个容器,这一节详细介绍.Grid一般是用表格(Grid.Row 和Grid.Column )的,比StackPanel更细致一些,但是,这么玩很麻烦,先横着竖着定义一大堆,然后把 ...

  7. 端口扫描命令nmap

    转:http://www.osyunwei.com/archives/2004.html 下面教大家在CentOS中用nmap查看主机端口: 一.安装nmap yum install nmap -y ...

  8. awk 指定{}内x的替换

    替换{}中的x为;   原字符串 oxo{axbxc}oxo{dxexf}oxo 结果 oxo{a;b;c}oxo{d;e;f}oxo     awk '{for(i=1;i<=NF;i++){ ...

  9. R 调用 python

    上一篇说了python使用 rpy2 调用 R,这里介绍R如何调用python.R的强项在于统计方面,尤其是专业的统计分析,统计检验以及作图功能十分强大,但是在通用性方面,就远不如Python了,比如 ...

  10. linux makefile字符串操作函数 替换subst、模式替换patsubst、去首尾空格strip、查找字符串findstring、过滤filter、反过滤filter-out、排序函数sort、取单词word、取单词串wordlist、个数统计words

    1.1       字符操作函数使用 在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能.make所支持的函数也不算很多,不过已经足够我们的操作了.函数调用后,函 ...