SqlBulkCopy 会自动启动事务吗?
Posted
技术标签:
【中文标题】SqlBulkCopy 会自动启动事务吗?【英文标题】:Does SqlBulkCopy automatically start a transaction? 【发布时间】:2014-12-22 09:18:31 【问题描述】:我正在通过SqlBulkCopy
插入数据,如下所示:
public void testBulkInsert(string connection, string table, DataTable dt)
using (SqlConnection con = new SqlConnection(connection))
con.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con))
bulkCopy.DestinationTableName = table;
bulkCopy.WriteToServer(dt);
这是否会自动包装在 SQL 事务中,以便如果在执行过程中出现问题,DB 将保持与开始批量插入之前相同的状态?还是会插入一半的数据?
即我有必要显式调用con.BeginTransaction
或者,如果我调用SqlBulkCopy
的构造函数,它接受一个字符串,这是让它在事务中发生的更好方法吗?
public void testBulkInsert(string connection, string table, DataTable dt)
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
bulkCopy.DestinationTableName = table;
bulkCopy.WriteToServer(dt);
我发现docs 在这件事上有点不清楚,因为他们最初是这么说的
默认情况下,大容量复制操作是作为独立的 手术。大容量复制操作以非事务方式发生, 没有机会回滚
但后来状态
默认情况下,大容量复制操作是它自己的事务。当你 想要执行专用的批量复制操作,创建一个新实例 SqlBulkCopy 与连接字符串,或使用现有的 没有活动事务的 SqlConnection 对象。在每种情况下, 大容量复制操作创建,然后提交或回滚 交易。
那么有必要这样做吗:
public void testBulkInsert(string connection, string table, DataTable dt)
using (SqlConnection con = new SqlConnection(connection))
con.Open();
using (SqlTransaction tr = con.BeginTransaction(IsolationLevel.Serializable))
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, tr))
bulkCopy.DestinationTableName = table;
bulkCopy.WriteToServer(dt);
tr.Commit();
【问题讨论】:
为什么不试试呢?文档的哪一部分让您认为它会这样做? 这部分:默认情况下,大容量复制操作是它自己的事务,但它也说大容量复制操作以非事务方式发生,与没有机会回滚所以......这有点令人困惑 【参考方案1】:这里没有来自SqlBulkCopy
msdn 文档中的文本
默认情况下,大容量复制操作是作为独立的 手术。 大容量复制操作以非交易方式发生, 没有机会回滚。如果您需要全部回滚 或部分批量复制发生错误时,您可以使用 SqlBulkCopy 托管事务,执行批量复制操作 在现有交易中,或被列入 System.Transactions 事务。
编辑: 从我给你的链接中正确阅读文档:
默认情况下,大容量复制操作是它自己的事务。当你 想要执行专门的大容量复制操作,创建一个新的 带有连接字符串的 SqlBulkCopy 实例,或使用 没有活动事务的现有 SqlConnection 对象。每个 方案,大容量复制操作创建,然后提交或滚动 退回交易。
这是为案例内部批量复制事务编写的,不是默认的!
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
connectionString, SqlBulkCopyOptions.KeepIdentity |
SqlBulkCopyOptions.UseInternalTransaction))
....
仔细查看SqlBulkCopyOptions.UseInternalTransaction
! 您在 SqlBulkCopy 类构造函数中显式指定 UseInternalTransaction 选项,以显式导致批量复制操作在其自己的事务中执行,从而导致每批批量复制操作在单独的事务中执行。由于不同的批次在不同的事务,如果在批量复制操作过程中发生错误,当前批次中的所有行将被回滚,但之前批次中的行将保留在数据库中。
如果由于发生错误需要回滚整个大容量复制操作,或者如果大容量复制应作为可回滚的较大进程的一部分执行,则可以向 SqlBulkCopy 提供 SqlTransaction 对象构造函数。
外部交易案例。
using (SqlTransaction transaction =
destinationConnection.BeginTransaction())
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
destinationConnection, SqlBulkCopyOptions.KeepIdentity,
transaction))
....
就像我在乞讨中所说的那样,答案是否定的,您应该使用现有事务或内部批量复制事务。阅读链接中的文档文件,了解更多信息。
如果你想进行交易,你应该使用我写的两种情况之一。
【讨论】:
在那些文档中说:默认情况下,批量复制操作是它自己的事务。当您想要执行专用的大容量复制操作时,请使用连接字符串创建一个新的 SqlBulkCopy 实例,或者使用没有活动事务的现有 SqlConnection 对象。在每种情况下,大容量复制操作都会创建、然后提交或回滚事务。 这是否意味着如果我使用using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
而不是我所拥有的,那么它将在事务中?还是自己打电话给con.BeginTransaction
更好?以上是关于SqlBulkCopy 会自动启动事务吗?的主要内容,如果未能解决你的问题,请参考以下文章