У меня есть блок кода, который выполняется в TransactionScope, и в этом блоке кода я делаю несколько обращений к БД. Выбирает, обновляет, создает и удаляет всю гамму. Когда я выполняю удаление, я выполняю его, используя метод расширения SqlCommand, который автоматически повторно отправляет запрос, если он заходит в тупик, поскольку этот запрос потенциально может зайти в тупик.
Я полагаю, что проблема возникает, когда возникает тупик, и функция пытается повторить запрос. Это ошибка, которую я получаю:
Транзакция, связанная с текущим соединением, завершена, но не была удалена. Транзакция должна быть удалена, прежде чем соединение можно будет использовать для выполнения операторов SQL.
Это простой код, который выполняет запрос (весь приведенный ниже код выполняется с использованием TransactionScope):
using (sqlCommand.Connection = new SqlConnection(ConnectionStrings.App))
{
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQueryWithDeadlockHandling();
}
Вот метод расширения, который повторно отправляет заблокированный запрос:
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;
}
}
Ошибка возникает в строке:
sqlCommand.ExecuteNonQuery();