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】:

这里没有来自SqlBulkCopymsdn 文档中的文本

默认情况下,大容量复制操作是作为独立的 手术。 大容量复制操作以非交易方式发生, 没有机会回滚。如果您需要全部回滚 或部分批量复制发生错误时,您可以使用 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 会自动启动事务吗?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server启动事务有几种方式?

SQL中事务有几种?

PHP PDO 事务自动回滚

自动关闭和启动 Amazon EC2 实例

如何在启动时禁用 MSVC 中的自动构建?

electron开机自动启动有用吗