[英]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.