J'ai un bloc de code qui s'exécute dans un TransactionScope et dans ce bloc de code, je fais plusieurs appels à la base de données. Sélections, mises à jour, créations et suppressions, toute la gamme. Lorsque j'exécute ma suppression, je l'exécute en utilisant une méthode d'extension de la SqlCommand qui soumettra à nouveau automatiquement la requête en cas de blocage, car cette requête peut potentiellement se bloquer.
Je pense que le problème se produit lorsqu'un blocage est atteint et que la fonction tente de soumettre à nouveau la requête. Voici l'erreur que je reçois :
La transaction associée à la connexion actuelle est terminée mais n'a pas été cédée. La transaction doit être éliminée avant que la connexion puisse être utilisée pour exécuter des instructions SQL.
Il s'agit du code simple qui exécute la requête (tout le code ci-dessous s'exécute dans le cadre de l'utilisation du TransactionScope) :
using (sqlCommand.Connection = new SqlConnection(ConnectionStrings.App))
{
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQueryWithDeadlockHandling();
}
Voici la méthode d'extension qui soumet à nouveau la requête bloquée :
public static class SqlCommandExtender
{
private const int DEADLOCK_ERROR = 1205;
private const int MAXIMUM_DEADLOCK_RETRIES = 5;
private const int SLEEP_INCREMENT = 100;
public static void ExecuteNonQueryWithDeadlockHandling(this SqlCommand sqlCommand)
{
int count = 0;
SqlException deadlockException = null;
do
{
if (count > 0) Thread.Sleep(count * SLEEP_INCREMENT);
deadlockException = ExecuteNonQuery(sqlCommand);
count++;
}
while (deadlockException != null && count < MAXIMUM_DEADLOCK_RETRIES);
if (deadlockException != null) throw deadlockException;
}
private static SqlException ExecuteNonQuery(SqlCommand sqlCommand)
{
try
{
sqlCommand.ExecuteNonQuery();
}
catch (SqlException exception)
{
if (exception.Number == DEADLOCK_ERROR) return exception;
throw;
}
return null;
}
}
L'erreur se produit sur la ligne :
sqlCommand.ExecuteNonQuery();