簡體   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)
                {

                }
            }
        }
    }
}

每當ExecuteNonQuery由於某些異常而失敗時,我都有一個重試機制,它將再次運行相同的查詢。在這種情況下,第二次(重試時)會出現以下異常-

“連接必須有效並且開放才能提交事務”

從根本上講,問題是,您在finally塊中提交了事務(該事務始終按設計運行),即使您可能已經回滾了事務並在catch塊中關閉了連接。

比較簡單的方法是在仍處於try塊中的情況下提交事務,因為畢竟,您只想在try中的所有代碼都成功的情況下提交事務。

話雖如此,您在try using一些奇怪的嵌套,並在其中using構造。 您應該盡量簡化using s之類的內容。 這樣,您也不必自己處理關閉的連接。 像這樣:

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;
    }
}

最后一點,有人可能會爭辯說,在這里絕對不需要使用事務:您只在此數據庫連接上執行一個查詢,這樣行得通,否則它將失敗,在這種情況下無論如何都不會回滾。 因此,除非在那里有多個查詢,否則不需要顯式事務(但我假設您只是簡化了示例以僅顯示單個查詢)。

我的錯,是我自己使用“ finally”(最后)錯誤地搞定的。因此,如果第一次嘗試查詢失敗,它將進入catch塊,這將觸發重新運行查詢的調用。第二次查詢執行將成功,事務將被提交。然后控制轉到第一個查詢的最后,它將再次嘗試提交已經回滾的事務。 因此,它將引發該異常。 因此,如果將提交移至主要try塊可解決此問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM