我需要计算来自 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 将在同一锁定期间按预期抛出 TimeoutException,这使 SqlBulkCopy.WriteToServer 方法无限期挂起。
以下是我们尝试过的方法——但都失败了——让 SqlBulkCopy.WriteToServer 在预期的时候持续抛出超时:
- MARS(多个活动结果集)开/关
- TableLock 开启与关闭
- 目的地作为堆表与索引表
- 更长/更短的 BulkTimeout 值(10 秒到 5 分钟)
- 内部与外部交易
现在,作为一种解决方法,我在 a) 将 WriteToServer 调用放在异步包装器中以便我可以自己计时,以及 b) 只调用 WriteToServer 一次;超时后,等到常规 SqlCommand成功后再尝试 WriteToServer。使用这些方法,我至少能够控制执行流程。