【问题标题】:Is it possible to use System.Transactions.TransactionScope with SqlBulkCopy?是否可以将 System.Transactions.TransactionScope 与 SqlBulkCopy 一起使用?
【发布时间】:2011-09-06 00:51:05
【问题描述】:

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

【问题讨论】:

标签: .net sql-server transactionscope sqlbulkcopy


【解决方案1】:

SqlBulkCopy 从不参与事务。 SqlCommand 也不这样做。常见的误解。在调用SqlConnection.Open 时执行登记。之后,在该连接上运行的任何东西都隐含地成为事务的一部分。事实上,它不再允许传递显式事务。

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

这很容易做到:

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. 请勿使用SqlBulkCopySqlTransaction 参数。通过null
  3. 不要使用SqlBulkCopyOptions.UseInternalTransaction
  4. 不要添加异常处理,除非你想真正做点什么。如果没有提交,则自动回滚。
  5. 使用using 语句进行清洁代码和确定性清理。除非必须,否则请勿手动关闭或处置任何这些对象。这将是多余的。

您可以使用您喜欢的任何批次大小,所有批次都将成为交易的一部分。因此,批处理的价值有限(特别是事务日志不能提前截断)。首先尝试不进行批处理。

【讨论】:

    【解决方案2】:

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

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

    Using Transactions with SqlBulkCopy

    【讨论】:

    • 我们涉及两个数据库是什么?
    • 这个答案没有解释被问到的 TransactionScope。
    【解决方案3】:

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

    批量加载的优点是您可以获得批量更新锁(多线程读取和多线程写入)。当使用 bcp、批量插入、带有 (tablock) 的 ssis 数据流任务、插入 (columns) 从 openrowset (bulk) 或 sqlbulkcopy 中选择列时,您会得到这个。这在尝试最小化加载时间和事务日志大小时非常方便(仅当您满足最少记录的要求时,这将为您节省数百万行的时间)。

    任何时候加载数据,事务日志都会成为瓶颈。如果时间至关重要,那么尽量减少记录的数量很重要。

    一旦满足批量大小(您指定提交的行数),事务就会提交并重新开始。如果指定batchsize 为0,则事务将覆盖整个文件并在出现任何数据问题时回滚。

    【讨论】:

    • 这很不幸。我将单行提交和批量加载到 multiple 表中,然后在另一个表中进行单行更新,必须全部成功或不成功。我希望很容易将提交和批量加载以及最终更新包装在一个TransactionScope 中。我只需要采取不同的方法。感谢您的详细回答,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2016-04-01
    • 2011-01-20
    • 2018-08-11
    • 2021-08-05
    • 2019-03-18
    • 2014-03-15
    相关资源
    最近更新 更多