非常简单的问题:是否可以将System.Transactions.TransactionScope
与SqlBulkCopy
一起使用?文档Transaction and Bulk Copy Operations没有提及任何内容(至少从.NET 4.0开始),我的测试表明它不会自动登记TransactionScope
。
答案 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.
}
这段代码就是您所需要的。可能的错误:
SqlTransaction
的{{1}}参数。通过SqlBulkCopy
。null
。SqlBulkCopyOptions.UseInternalTransaction
语句进行清除代码和确定性清理。除非必须,否则请勿手动关闭或处置任何这些对象。这将是多余的。您可以使用您喜欢的任何批量大小,所有批次都将成为交易的一部分。因此,批处理具有有限的价值(特别是事务日志不能提前截断)。首先尝试不批处理。
答案 1 :(得分:4)
要执行跨越所有批次(以及可选地跨越其他数据库语句)的原子SqlBulkCopy导入,我们需要使用事务。以下步骤概述了使用SqlBulkCopy进行事务的过程:
答案 2 :(得分:3)
在批量加载中定义事务的唯一方法(据我所知)是指定batchsize。
批量加载的优点是您获得批量更新锁(多线程读取和多线程写入)。使用bcp,BULK INSERT,与(TABLOCK)一个SSIS数据流任务,一个插入(列)从OPENROWSET(散装)选择列,或SqlBulkCopy的,当你得到这个。试图既加载时间和事务日志的大小减少(只有当你已经满足了最低限度记录的要求,这会为你节省数百万行的时间)时,这是很方便的。
无论何时加载数据,事务日志都将成为瓶颈。如果时间至关重要,那么最小化记录的数量非常重要。
一旦batchsize是满足该交易被提交,然后重新开始(您指定要提交的行数)。如果指定batchsize为0,则事务将覆盖整个文件并在出现任何数据问题时回滚。