命令失败后,Npgsql不提交事务

时间:2011-09-23 08:16:33

标签: .net sql postgresql transactions npgsql

我在.NET 4.0下使用Npgsql 2.0.11来修改PostgreSQL 9.0数据库。该程序在一次交易中对数据库进行了许多修改。

在提交之前,我运行SELECT语句,有时会失败(例如,超时)。我吞下了异常并继续进行交易。没有错误,所以看起来好像一切正​​常,但实际上数据库根本没有修改过!

我的猜测是失败的SELECT回滚整个事务。我可以阻止这种情况(即,事务仍然提交)或至少检测到这种情况并抛出异常,因此用户知道提交失败了吗?

我知道在这个特定的情况下我可以在事务之外移动SELECT,但我更关心的是解决这个问题。提交不提交是一个非常严重的问题,我想确保它不被发现。

3 个答案:

答案 0 :(得分:7)

我对Npgsql一无所知,但我可以谈谈PostgreSQL的行为。当PostgreSQL事务中发生任何错误时,事务将被标记为 invalid ,直到它被关闭。 (他们的术语是“中止”,我认为这是误导性的。)此外,这是恕我直言,如果你COMMIT无效的交易,它“成功”,但效果与ROLLBACK相同。您可以在psql REPL中观察到这一点;它将打印ROLLBACK以响应您的COMMIT命令,但不会发出错误信号。

您可以在最终SAVEPOINT之前创建SELECT。如果失败,则ROLLBACK为保存点名称;这将使您退出无效状态,并允许您提交事务的前一部分。

答案 1 :(得分:0)

我最后编写了一个小包装器方法,尝试在提交之前执行一个简单的语句作为事务的一部分,这有效地检测问题。

    public static void CommitTransaction(NpgsqlConnection conn, NpgsqlTransaction tran)
    {
        using (var command = new NpgsqlCommand("SELECT 1", conn, tran))
        {
            try
            {
                command.ExecuteScalar();
            }
            catch (NpgsqlException ex)
            {
                if (ex.Code == "25P02")
                    throw new Exception("The transaction is invalid...");
                throw;
            }
        }

        tran.Commit();
    }

修复是 Morg。 Ryan Culpepper 的答案:要么在事务之外运行语句,要么事先创建一个SAVEPOINT并向它创建ROLLBACK出错了。

答案 2 :(得分:-1)

在交易中出现问题,但交易完成对交易不是很正确吗?

所以基本上,如果它可能会失败并且您不关心它,请不要将它放在交易中,而不要让它失败。

使用交易,因为它们意图使用,您不会有任何问题;)