[英]Detecting rollback in SQL Server
当涉及两个或多个语句时尝试检测回滚条件。 对于SqlCommand.ExecuteNonQuery
方法, 文档说
如果未检测到有助于计数的语句,则返回值为 -1。 如果发生回滚,则返回值也是 -1。
我故意插入-1
作为具有引用完整性约束的引用表中的无效条目。
string sql = $@"
BEGIN TRANSACTION
BEGIN TRY
DELETE FROM CustomerContact WHERE CustomerId = @Id
INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Connection.Open();
command.Parameters.Add("Id", SqlDbType.Int).Value = id;
int result = command.ExecuteNonQuery();
Console.WriteLine(result); // -> returns affected deleted rows but not -1
}
回滚按预期工作,但我没有从ExecuteNonQuery
获得-1
,相反,我从DELETE
操作(第一条语句)中获得了许多受影响的行
我之前确实使用过SqlTransaction
,但我正在测试基于嵌入式 SQL 的事务的行为。
我建议您只输入CATCH
块以指示错误并发生相应的回滚,而不是尝试检测ROLLBACK
本身。
最好指定SET XACT_ABORT ON;
使用 T-SQL 事务确保事务在超时的情况下立即回滚。 这是因为超时发生在客户端,其中 API 取消正在运行的查询并阻止带有ROLLBACK
的 CATCH 块执行。 然后,连接将通过打开的事务返回到池中,并且锁尚未释放。 尽管当池连接被重用/重置或关闭时事务最终会回滚,但 XACT_ABORT 设置将导致立即发生并释放资源锁。
下面是我在大多数情况下推荐的 T-SQL 事务管理和结构化错误处理模式。 另外,请注意自由使用分号以避免意外。
string sql = $@"
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM CustomerContact WHERE CustomerId = @Id;
INSERT INTO CustomerContact(CustomerId, ContactId) VALUES (3, -1);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
THROW;
END CATCH";
try
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Connection.Open();
command.Parameters.Add("Id", SqlDbType.Int).Value = id;
int result = command.ExecuteNonQuery();
Console.WriteLine(result); // -> returns affected deleted rows but not -1
}
}
catch
{
Console.WriteLine('handle exception here');
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.