是否可以将System.Transactions.TransactionScope与SqlBulkCopy一起使用?

时间:2011-09-06 00:51:06

标签: .net sql-server transactionscope sqlbulkcopy

非常简单的问题:是否可以将System.Transactions.TransactionScopeSqlBulkCopy一起使用?文档Transaction and Bulk Copy Operations没有提及任何内容(至少从.NET 4.0开始),我的测试表明它不会自动登记TransactionScope

3 个答案:

答案 0 :(得分:36)

SqlBulkCopy永远不会参与交易。 SqlCommand也不这样做。常见的误解。征募是在SqlConnection.Open被调用时执行的。之后,在该连接上运行的任何内容都是隐式的事务的一部分。实际上,允许不再传递显式事务。

如果您希望SqlBulkCopy使用System.Transactions.Transaction参与TransactionScope,则必须在您打开连接时设置交易。

这很容易做到:

using (var tran = new TransactionScope(...))
using (var conn = new SqlConnection(connStr))
{
  conn.Open(); //This enlists.

  using (var sqlBulkCopy = new SqlBulkCopy(conn)) {
    sqlBulkCopy.WriteToServer(...);
  }

  tran.Complete(); //Commit.
}

这段代码就是您所需要的。可能的错误:

  1. 交易必须尽早开启。
  2. 请勿使用SqlTransaction的{​​{1}}参数。通过SqlBulkCopy
  3. 请勿使用null
  4. 除非您想要实际执行某些操作,否则不要添加异常处理。如果没有提交,则回滚是自动的。
  5. 使用SqlBulkCopyOptions.UseInternalTransaction语句进行清除代码和确定性清理。除非必须,否则请勿手动关闭或处置任何这些对象。这将是多余的。
  6. 您可以使用您喜欢的任何批量大小,所有批次都将成为交易的一部分。因此,批处理具有有限的价值(特别是事务日志不能提前截断)。首先尝试不批处理。

答案 1 :(得分:4)

要执行跨越所有批次(以及可选地跨越其他数据库语句)的原子SqlBulkCopy导入,我们需要使用事务。以下步骤概述了使用SqlBulkCopy进行事务的过程:

  1. 创建一个到目标数据库服务器的SqlConnection。
  2. 打开连接。
  3. 创建一个SqlTransaction对象。
  4. 创建传入SqlTransaction对象的SqlBulkCopy对象 进入构造函数。
  5. 在a中执行导入 - 对WriteToServer的调用 试试......抓住阻止。     如果操作完成,则提交事务;如果失败,请回滚。
  6. Using Transactions with SqlBulkCopy

答案 2 :(得分:3)

在批量加载中定义事务的唯一方法(据我所知)是指定batchsize。

批量加载的优点是您获得批量更新锁(多线程读取和多线程写入)。使用bcp,BULK INSERT,与(TABLOCK)一个SSIS数据流任务,一个插入(列)从OPENROWSET(散装)选择列,或SqlBulkCopy的,当你得到这个。试图既加载时间和事务日志的大小减少(只有当你已经满足了最低限度记录的要求,这会为你节省数百万行的时间)时,这是很方便的。

无论何时加载数据,事务日志都将成为瓶颈。如果时间至关重要,那么最小化记录的数量非常重要。

一旦batchsize是满足该交易被提交,然后重新开始(您指定要提交的行数)。如果指定batchsize为0,则事务将覆盖整个文件并在出现任何数据问题时回滚。