Ho un blocco di codice eseguito all'interno di TransactionScope e all'interno di questo blocco di codice eseguo diverse chiamate al DB. Seleziona, aggiorna, crea ed elimina, l'intera gamma. Quando eseguo la mia eliminazione, la eseguo utilizzando un metodo di estensione di SqlCommand che ripubblicherà automaticamente la query se si blocca in quanto questa query potrebbe potenzialmente raggiungere un deadlock.TransactionScope precocemente completato
Credo che il problema si verifichi quando si verifica un deadlock e la funzione tenta di inviare nuovamente la query. Questo è l'errore che ricevo:
La transazione associata alla connessione corrente è stata completata ma non è stata eliminata. La transazione deve essere eliminata prima che la connessione possa essere utilizzata per eseguire istruzioni SQL.
Questo è il semplice codice che esegue la query (tutto il codice sotto esegue all'interno usando del TransactionScope):
using (sqlCommand.Connection = new SqlConnection(ConnectionStrings.App))
{
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQueryWithDeadlockHandling();
}
Qui è il metodo di estensione che invia nuovamente la query punto morto:
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'errore si verifica sulla linea:
sqlCommand.ExecuteNonQuery();
Grazie per il suggerimento sulla soppressione delle transazioni sulle istruzioni select. Questo ha aiutato a risolvere un problema di timeout che mi stava facendo impazzire. –
Risposta fantastica. Questo mi ha fatto impazzire su una raccolta di raccolta selezione/inserimento di istruzioni SQL. L'aggiunta dell'opzione Elimina automaticamente risolve il problema. – IoChaos
Santo schifo grazie! Sono stato a lottare con questo tutto il giorno. Una soluzione così semplice. – rossipedia