![](/img/trans.png)
[英]C# MySQL commit transaction is not working (Connection must be valid and open to commit transaction)
[英]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.