繁体   English   中英

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

[英]Npgsql does not commit transaction after failed command

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

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

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

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

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

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

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

    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。

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

所以基本上,如果它可能失败并且您不关心它,请不要将它放在事务中,并且不能失败。

使用交易,因为它们意味着使用,你不会有任何问题;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM