我试图找出将 SqlBulkCopy 与 SqlBulkCopyOptions.UseInternalTransaction
复制选项一起使用和不使用它之间的区别,但在我的测试应用程序中,我没有检测到任何区别。例如,如果 BatchSize
为 0 并且我添加了 100 条记录(在 DataTable
中),其中记录号 50 在将其添加到数据库表时导致错误,我得到 0 条记录 table 。例如,如果 BatchSize
设置为 10,我将获得 40 条记录(4 批 10 条记录,第五批包括错误记录并导致批量复制中止)。 SqlBulkCopyOptions.UseInternalTransaction
是否设置并不重要,我总是得到相同的结果。似乎总是在内部交易中复制批处理。
如果您对我的测试应用感兴趣,请看这里:SqlBulkCopy-Error-and-Transaction-Test.zip
我的问题是:
SqlBulkCopyOptions.UseInternalTransaction
是否已过时,因为SqlBulkCopy
始终使用内部事务?- 如果不是:这个选项的实际含义是什么?在哪些情况下会有所作为?
希望有人能说明
编辑:
根据答案和评论,我认为我的问题还不够清楚。我知道文档。它说“默认情况下,批量复制操作是它自己的事务。”并且每个批处理在传递 UseInternalTransaction
时都使用它自己的事务。但是如果这意味着默认情况下大容量复制操作只对整个大容量复制使用一个事务(而不是每个批处理一个事务),如果我将 BatchSize 设置为特定大小并且在之后设置一个批处理,我将不会在数据库中获取记录第一个导致错误。如果只使用一个事务,则所有添加到事务日志的记录都将被回滚。但是我得到了包含错误记录的批处理之前的批处理记录。根据这个,似乎默认情况下每个批处理都在它自己的事务中执行。这意味着我是否通过 UseInternalTransaction
没有区别。如果我在这里走错了路,如果有人能澄清一下,我将不胜感激。
一个事实可能很重要:我使用的是 SQL Server 2012。也许 SQL Server 2008 的行为有所不同。我会检查一下。
编辑: 感谢 usr 的回复,我想我找到了答案:我进行了一些调试和分析,发现如果未定义 UseInternalTransaction,则私有(private)字段 _internalTransaction 确实未设置。 SqlBulkCopy 然后不使用自己的(内部)事务。但是分析表明 SqlBulkCopy 使用 TDS(表格数据流)来复制数据(无论 BatchSize 是什么)。我没有找到太多关于 TDS 的信息,尤其是对于 SQL Server,但我假设 SQL Server 在内部事务中执行 TDS 批量复制操作。因此,UseInternalTransaction 对于 SQL Server 来说似乎有点多余,但为了安全起见,我会设置它。
最佳答案
如果你设置这个选项,那么 SQLBulkCopy 类将添加一个
_internalTransaction = _connection.BeginTransaction();
围绕每个批处理。
但此选项与 SQL Server 没有实际区别,因为默认情况下事务无论如何都以自动提交模式运行。
唯一可观察到的区别是它执行您还没有尝试传递外部事务的验证。
以下将成功并回滚所有批处理
var transaction = sourceConnection.BeginTransaction();
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(sourceConnection, SqlBulkCopyOptions.Default, transaction))
{
bulkCopy.BatchSize = 50;
bulkCopy.DestinationTableName = "dbo.foobar";
bulkCopy.WriteToServer(dt);
}
transaction.Rollback();
传递 SqlBulkCopyOptions.UseInternalTransaction
失败并出现错误
Must not specify SqlBulkCopyOption.UseInternalTransaction and pass an external Transaction at the same time.
我想知道如果 SET IMPLICIT_TRANSACTIONS ON;
之前在连接上运行以关闭自动提交模式但 SqlBulkCopy
的重载是否会有所不同采用连接对象的构造函数返回“意外的现有事务”。无论如何在这两种情况下都会出错 - 并且采用连接字符串的重载只会创建一个新连接。
关于.net - SqlBulkCopy:传递 SqlBulkCopyOptions.UseInternalTransaction 和不传递它有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10136814/