我面临
SqlTransaction
的问题,其中事务对象被回滚并意外处置。当在未知表上调用 SET IDENTITY_INSERT 时,这似乎会特别发生。我没有看到与其他类型的 sql 错误相同的问题。这是一个最小的例子:
using Microsoft.Data.SqlClient;
var connStr = @"server=(localdb)\MSSQLLocalDB;integrated security=True;";
using var conn = new SqlConnection(connStr);
conn.Open();
using var tran = conn.BeginTransaction();
try
{
using var cmd = conn.CreateCommand();
cmd.Transaction = tran;
cmd.CommandText = "SET IDENTITY_INSERT badtable ON"; // transaction is disposed with this
// cmd.CommandText = "SELECT 1 FROM badtable"; // transaction is NOT disposed with this
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine("Transaction disposed: " + (tran.Connection == null).ToString());
throw;
}
我很好奇为什么交易要在这里处理。
SELECT 1 FROM bedtable
失败
消息 208,级别 16,状态 1,第 28 行 无效的对象名称“bedtable”。
SET IDENTITY_INSERT bedtable ON
失败
消息 1088,级别 16,状态 11,第 20 行找不到对象 “bedtable”,因为它不存在或您没有权限。
所以它们是不同的错误,结果错误的影响是不同的。错误 208 是延迟名称解析失败,它会中止范围,但不会中止整个批次,并且不会回滚当前事务。
错误 1088 中止整个批次并回滚事务。
是的,这没有什么明显的意义。但众所周知,T-SQL 中的错误处理非常复杂。参见,例如:
https://www.sommarskog.se/error-handling-I.html#scope-abortion