简体   繁体   English

连接必须有效并且打开才能在尝试执行失败的查询时提交sqllite数据库的事务

[英]Connection must be valid and open to commit transaction for sqllite database while retrying to execute the failed query

public static void SetStatus( Status statusObject,int retryCount)
{
    if (statusObject != null)
    {
        using (SqliteConnection dbConn = new SqliteConnection(dbURL))
        {
            IDbTransaction dbTransaction = null;
            try
            {
                dbConn.Open();
                dbTransaction = dbConn.BeginTransaction();
                new SqliteCommand(some_query, dbConn).ExecuteNonQuery();
            }
            catch (Exception e)
            {
                dbTransaction.Rollback();
                dbConn.Close();
                if (retryCount > 0)
                {
                    SetStatus(statusObject, --retryCount);
                    return;
                }
                else
                    throw e;
            }
            finally
            {
                try { dbTransaction.Commit(); }
                catch (Exception e)
                {

                }
            }
        }
    }
}

Whenever ExecuteNonQuery fails due due to some exception I have a retry mechanism which will run the same query again.In that case during the second time(while retrying) the following exception comes- 每当ExecuteNonQuery由于某些异常而失败时,我都有一个重试机制,它将再次运行相同的查询。在这种情况下,第二次(重试时)会出现以下异常-

"Connection must be valid and open to commit transaction" “连接必须有效并且开放才能提交事务”

The problem is basically, that you commit the transaction in the finally block—which runs always per design—even though you may already have rolled back the transaction and closed the connection in the catch block. 从根本上讲,问题是,您在finally块中提交了事务(该事务始终按设计运行),即使您可能已经回滚了事务并在catch块中关闭了连接。

The easier way would be to commit the transaction while still in the try block, because after all, you only want to commit the transaction if all the code in the try succeeded. 比较简单的方法是在仍处于try块中的情况下提交事务,因为毕竟,您只想在try中的所有代码都成功的情况下提交事务。

That being said, you are having some odd nesting with the try and using constructs there. 话虽如此,您在try using一些奇怪的嵌套,并在其中using构造。 You should try to keep things like using s as concise as possible. 您应该尽量简化using s之类的内容。 That way you will also not have to deal with closing connections yourself. 这样,您也不必自己处理关闭的连接。 Something like this: 像这样:

public static void SetStatus(Status statusObject, int retryCount)
{
    if (statusObject == null)
        return;

    try
    {
        using (var dbConn = new SqliteConnection(dbURL))
        {
            IDbTransaction dbTransaction = null;
            try
            {
                dbConn.Open();
                dbTransaction = dbConn.BeginTransaction();
                new SqliteCommand(some_query, dbConn).ExecuteNonQuery();
                dbTransaction.Commit();
            }
            catch
            {
                // transaction might be null if the connection couldn’t be opened
                dbTransaction?.Rollback();
                throw;
            }
        }
    }
    catch (Exception ex)
    {
        if (retryCount > 0)
            SetStatus(statusObject, --retryCount);
        else
            throw ex;
    }
}

One final note, one could argue that using a transaction is absolutely not necessary here: You are only executing a single query on this database connection, so either that works, or it will fail in which case there is not something to rollback anyway. 最后一点,有人可能会争辩说,在这里绝对不需要使用事务:您只在此数据库连接上执行一个查询,这样行得通,否则它将失败,在这种情况下无论如何都不会回滚。 So unless you are having multiple queries there, you don't need an explicit transaction (but I'll just assume that you just reduced your example to show just a single query). 因此,除非在那里有多个查询,否则不需要显式事务(但我假设您只是简化了示例以仅显示单个查询)。

My bad,screwed up using "finally" improperly myself.So if the query fails at first attempt it would go to catch block which will fire the call to re run the query.Second time query execution would be successful and transaction would be committed.Then the control goes to finally of first query which will again try to commit the already rolled back transaction. 我的错,是我自己使用“ finally”(最后)错误地搞定的。因此,如果第一次尝试查询失败,它将进入catch块,这将触发重新运行查询的调用。第二次查询执行将成功,事务将被提交。然后控制转到第一个查询的最后,它将再次尝试提交已经回滚的事务。 So,it would throw that exception. 因此,它将引发该异常。 So,if the moving the commit to main try block fixed the issue. 因此,如果将提交移至主要try块可解决此问题。

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

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