SqlTransaction вызывает сбой приложения при ошибке?

Вот некоторая предыстория: Периодически наш сайт падает до такой степени, что приходится перезапускать IIS; это почти всегда происходит в течение часа после исправления DLL (мы используем проект веб-сайта, а не проект веб-приложения, поэтому каждая страница ASPX является отдельной библиотекой DLL).

Проведя некоторое исследование, я обнаружил, что наш доморощенный DAL может при отладке привести к тому, что встроенный веб-сервер с Visual Studio фактически перестанет работать и выключится, если обнаружит ошибку SQL в хранимой процедуре (я имею в виду, что это не только генерировать исключение, которое отображается в браузере, на самом деле это говорит о том, что на веб-сервере произошла ошибка и его необходимо закрыть!)

При дальнейшем копании ошибка, похоже, связана с использованием транзакций для всего (включая операторы Select) в DAL. Кажется, происходит следующее:

  1. Пытается выполнить хранимую процедуру, хранимая процедура завершается сбоем из-за отсутствия/недопустимого столбца или другой ошибки.
  2. Код приложения ловит ошибку и выдает ее повторно (плохо, да, но я этого не писал).
  3. Транзакция пытается зафиксироваться, несмотря на исключение, получает NullReferenceException в строке transaction.Commit() (кажется, в свойстве Connection, потому что есть объект транзакции). Кроме того, кажется, что этот NullRef не может быть пойман (я попробовал демонстрацию, которая принудительно завершилась сбоем с недопустимым Sproc, и NullRef так и не был пойман, хотя вывод ошибки дал его тип как System.NullReferenceException)
  4. Транзакция выдает ошибку, которая говорит что-то вроде «Транзакция завершена и больше не может использоваться».
  5. ??? но веб-сервер VS падает. Отладка этой части, похоже, зависает на указанном выше исключении, никогда не выходя из метода.

Теперь я не знаю, является ли это причиной сбоя IIS, но это кажется довольно подозрительным, и в любом случае это вопиющая ошибка.

Не имея дела с транзакциями раньше и имея о них только общее представление, мой первый вопрос: почему транзакция все еще пытается зафиксироваться после того, как было выдано исключение? Мой второй вопрос заключается в том, как исправить неудачную фиксацию и предположительно бесконечный цикл исключений, пока сервер не умрет. Разве не имеет смысла добавить что-то вроде этого (метод принимает параметр SqlTransaction с именем transaction):

catch (SqlException se) 
{
    if (transaction != null)
    {
        transaction.Rollback();
    }
    throw;
}

Устранит ли это небольшое изменение постоянный цикл исключений, который, как мне кажется, приводит к сбою IIS? Сам DAL чрезвычайно хрупок и используется конкретно в сотнях файлов, поэтому я не могу правильно переписать его с нуля.

ИЗМЕНИТЬ Весь блок кода таков (опять же, устаревший код — используется старый помощник блока доступа к данным Microsoft):

    public static DataSet ExecuteDatasetStoredProc(SqlConnection conn, String storedProcName, SqlTransaction transaction, params SqlParameter[] storedProcParms)
    {
        try
        {
            // Execute the stored proc
            if (transaction != null)
            {
                return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, storedProcName, storedProcParms);
            }
            else
            {
                return SqlHelper.ExecuteDataset(conn, CommandType.StoredProcedure, storedProcName, storedProcParms);
            }
        }
        catch (SqlException se)
        {
            throw new ApplicationException("Error calling " + storedProcName + ". " + se.Message, se);
        }
    }

Однако, если блок catch выполняется, транзакция все еще пытается зафиксироваться, и это, по-видимому, вызывает зависание.


person Wayne Molina    schedule 16.12.2011    source источник
comment
для начала опубликуйте весь блок кода, где у вас есть код транзакции. Нулевая ссылка означает, что вы не создали экземпляр транзакции.. например, транзакция SQLTransaction; затем вы должны назначить эту транзакцию объекту SqlCommand sqlComm.Transaction = trans что-то вроде этого. точные параметры, надеюсь, вы не делаете и выбираете *, когда вам нужно всего несколько полей, а не много.. нужно увидеть код и запросы   -  person MethodMan    schedule 16.12.2011


Ответы (1)


также измените свой, если вы завернете свой транзакционный код в попытку поймать

Try
{
// your code that you assign and execute the SQl

}
catch (SQLException sqlex)
{
  try 
  {
    //try to do the rollback here.. don't always assume the commit or rollback will work
  }
  catch (Your SQL Exception ex)
  {
  }
}
person MethodMan    schedule 16.12.2011
comment
Не надо откатывать. stackoverflow.com/questions/18388852/ - person Jim G.; 01.07.2021