我需要计算来自SqlBulkCopy的顺序超时异常。为了测试这一点,我使用一个外部应用程序来启动事务并锁定目标表。

仅在第一次调用时,SqlBulkCopy才会在预期时引发超时异常。我们尝试使用外部连接和事务,以及使用连接字符串和内部事务。对于外部连接和事务,无限的等待永远不会在打开连接或开始或提交事务时进行,而总是在.WriteToServer()进行。

是否有某种方法可以使SqlBulkCopy.WriteToServer()达到.BulkCopyTimeout限制后将可靠地抛出超时异常?

public void BulkCopy(string connectionString, DataTable table, int bulkTimeout)
{
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
        connectionString,
        SqlBulkCopyOptions.UseInternalTransaction))
    {
    bulkCopy.BulkCopyTimeout = bulkTimeout;//e.g. 120 sec.
    //... fill with data, map columns...
    bulkCopy.WriteToServer(table);
    // ^^^^ waits indefinitely, doesn't throw until *after*
    //      the lock is released.
    }
}

我更喜欢让异常冒出来,而不是在using块的范围内处理它们,但是我总是可以重新抛出。非常感谢您的见解。

更新1:

仍然没有解决方案。尽管发现了有趣的行为-正常的SqlCommand会在使SqlBulkCopy.WriteToServer方法无限期挂起的同一锁定期间按预期方式抛出TimeoutException。

以下是我们尝试过但都失败了的方法,以使SqlBulkCopy.WriteToServer能够在预期的情况下持续抛出超时:
  • MARS(多个事件结果集)开/关
  • TableLock打开与关闭
  • 作为堆表与索引表
  • 的目标
  • 较长/较短的BulkTimeout值(10秒至5分钟)
  • 内部与外部事务

  • 现在,作为一种解决方法,我在以下两种方法之间进行交替:a)将WriteToServer调用放入异步包装器中,以便我自己进行计时;以及b)仅调用一次WriteToServer;超时后,请等待常规SqlCommand成功后再尝试WriteToServer。使用这些方法,我至少能够控制执行流程。

    最佳答案

    您是否尝试过将SqlBulkOptions.TableLock选项传递给SqlBulkCopy?该选项(引号)表示它将:



    因此,如果有另一个处理过程锁定该表,则将阻止获得该锁定,并且从理论上讲,这将可靠地使超时。

    更新:
    我设置了自己的测试工具,无法复制。为了锁定表,我在SSMS中启动了一个事务SELECT * FROM TargetTable WITH (HOLDLOCK)。我使用了与问题中包含的相同的BulkCopy方法,使用内部事务,批量加载超时为30秒。 30秒后,每次尝试进行批量复制的尝试均会超时。然后,当我回滚SSMS事务时,它会成功。

    我正在使用SQL Server 2008 Express,.NET 3.5。

    这与第一次尝试后的情况不一样,批量加载超时未正确传递?即不是以某种方式将其设置为“不确定”。

    更新2:
    还打开了连接字符串中的“多个事件结果集”支持,每次仍然对我而言始终是超时的。

    关于c# - SqlBulkCopy.WriteToServer不可靠地服从BulkCopyTimeout,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2209387/

    10-11 19:30