这个交易是否正在为我回滚(编辑)
本文关键字:编辑 交易 是否 | 更新日期: 2023-09-27 18:36:09
如果我通过尝试创建现有表导致错误,则现有事务似乎已经回滚了自己:
private void CreateSomeThings()
{
SqlConnection SqlConn = new SqlConnection(ConnectionString);
SqlConn.Open();
(new SqlCommand("BEGIN TRANSACTION", SqlConn)).ExecuteNonQuery();
try
{
(new SqlCommand("CREATE TABLE sometable ([some_id] [int] IDENTITY(1,1) NOT NULL)", SqlConn)).ExecuteNonQuery();
// Create the table again, but carry on by catching the exception
try
{
(new SqlCommand("CREATE TABLE sometable ([some_id] [int] IDENTITY(1,1) NOT NULL)", SqlConn)).ExecuteNonQuery();
}
catch (Exception)
{
}
// If another exception is thrown
(new SqlCommand("bingy bongy boo", SqlConn)).ExecuteNonQuery();
(new SqlCommand("COMMIT TRANSACTION", SqlConn)).ExecuteNonQuery();
}
catch (Exception Ex)
{
try
{
// ... then this command will fail with "no corresponding BEGIN TRANSACTION"
(new SqlCommand("ROLLBACK TRANSACTION", SqlConn)).ExecuteNonQuery();
}
catch (Exception Ex2)
{
throw;
}
}
}
我想了解发生了什么以及为什么。我希望事务回滚是我的责任 - 对于其他错误,它不会这样做:例如,如果我只调用"bingy bongy",则只有调用会抛出异常,然后我ROLLBACK
异常而没有任何问题。
SQL Server 可以单方面决定回滚您的事务。这是 SQL Server 中一个严重的设计缺陷,因为您的应用程序永远无法知道事务是否仍处于活动状态。没有很好地记录哪些类型的错误回滚以及哪些类型的错误不会。例如,我想我记得唯一键冲突和其他数据错误不会回滚。但其他人会这样做。有些错误甚至会终止连接(这种情况很少见,也不是设计缺陷)。
我建议您以这样的方式进行编码:在第一个错误时中止事务,然后失败或重试所有内容。这为您省去了很多麻烦。希望每批执行一条语句,否则您可能会在事务之外运行第二条语句。
如果你真的想继续追查错误,你必须做两件事:
- 构建不回滚错误的白名单。在这种情况下,您可以继续前进。
SELECT @@TRANCOUNT
检查交易是否仍然有效。
您需要将
事务对象传递给所使用的每个命令,以使它们参与同一事务。
通常的模式是:
using (var conn = new SqlConnection("your connection string here"))
{
SqlTransaction trans = null;
try
{
conn.Open();
trans = conn.BeginTransaction();
using (SqlCommand command = new SqlCommand("command text here", conn, trans))
{
// do your job
}
trans.Commit();
}
catch (Exception ex)
{
try
{
// Attempt to roll back the transaction.
if (trans != null) trans.Rollback();
}
catch (Exception exRollback)
{
// Throws an InvalidOperationException if the connection
// is closed or the transaction has already been rolled
// back on the server.
}
}
}