Npgsql如何处理失败的事务?

9
在一个ASP.NET应用程序(C#)中,我们使用Postgres作为后端和Npgsql作为数据提供者。几天前我们遇到了严重的数据丢失问题。我检查了代码并发现了这样的代码:
    var transaction = connection.BeginTransaction();
    //some crud operation here  
    transaction.Commit()

有人坚称Npgsql会自行处理异常并在事务过程中出现问题时自动回滚事务。

我认为这种想法过于乐观,应该将代码放入try和catch块中,并显式调用事务回滚:

 var transaction = connection.BeginTransaction();
 try
    {
        //some crud operation here        
        transaction.Commit
    }catch(Exception ex)
    {
        transaction.Rollback();
    }

这是错的吗?

此外,回滚事务总是有效的吗?我在某个地方读到,只有在出现Postgres异常(例如语法错误)时才有效,但在其他类型的异常情况下不会起作用。有人可以澄清一下这一点吗?

2个回答

11
另一种方法可能是:

另一种方法可能是:

using( var tx = connection.BeginTransaction())
{
    .. do som database stuff ..

    tx.Commit();
}

在未提交的事务上执行Dispose(释放资源)会导致回滚,并且资源将被释放!


2
应该将其标记为已接受的答案。 - Ciapeczka

6

如果发生错误,PostgreSQL将自动终止事务,但不会回滚。

只有在以下情况下才完成事务:

  1. 断开连接

  2. 使用 COMMITROLLBACK 结束事务(两种情况都会回滚)

在错误发生和事务结束之间发送的所有语句都将被忽略。

因此,您应该使用 try/catch 块并进行回滚。

ROLLBACK 将完全撤消当前事务,无论是否出现错误。


1
如果错误来自数据库,则事务被中止但尚未回滚。如果异常来自.NET,则事务仍处于活动状态(除非提供程序中止了它)。在两种情况下,您需要显式回滚以结束事务。 - Laurenz Albe
明白了!非常感谢! - paolo_tn
1
@ArturBeljajev 我觉得没有人在谈论 SQL 语句。 - Laurenz Albe
@LaurenzAlbe 我有点困惑这句话的意思:"PostgreSQL会自动中止,但不会回滚"。也许是我理解错了... - Artur INTECH
1
@ArturBeljajev 我明白了。也许我没有描述清楚。如果在事务中出现错误,您会进入“空闲事务(已中止)”状态,并且需要运行“ROLLBACK”才能将其退出该状态。 - Laurenz Albe
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接