我对这些超时的理解如下:
DbCommand.CommandTimeout
控制 Sql 命令在自发停止并将控制权返回给 C# 调用代码之前运行的时间(以抛出超时的形式SqlException
。)
WAITFOR DELAY '00:00:05' And you set your
DbCommand.CommandTimeoutto
00:00:01`,那么您的 C# 将在 1 秒后抛出异常,而不是 5 秒。scopeTimeout
上的 TransactionScope
ctor 参数控制范围在被释放时是否回滚。它不能中断 SQL 执行 - 它只会在调用 scope.Dispose()
方法时触发异常。
WAITFOR DELAY '00:00:05'
并且您将 scopeTimeout
设置为 00:00:01
,那么您的 C# 将在 5 秒后抛出异常,在此之前不会被中断。我编写了测试来验证我的代码库中的这两种行为,假设仅存在两种超时中的一种,并且它们工作正常。
如果我为“scopeTimeout = 3s; CommandTimeout = 1s; SQL WAITFOR = 5s”创建测试,那么我预计 CommandTimeout 将优先,并且它将在 1 秒后抛出 SQL 异常。测试也证实了这一点。
最后,如果我创建“scopeTimeout = 1s; CommandTimeout = 3s; SQL WAITFOR = 5s”的测试,那么我预计该命令在抛出之前仍将运行 3s,然后范围将执行 [某事,TBC ] 当它处置时。
但我实际看到的是 SQL 运行了整整 5 秒!即...
设置较短的scopeTimeout似乎会完全禁用CommandTimeout!!
为什么会发生这种情况,有什么方法可以预防吗?
“所有服务器端 transactionScope 都有无限超时”对于 SQL Server 来说是一个好方法。
在代码中创建 TransactionScope 的地方,您并不真正知道事务内的任何操作是否可能长时间运行。