Как перехватить SQLException в C #?

#c# #sql-server

#c# #sql-server

Вопрос:

Здесь я попытался перехватить исключение sql с помощью innerexception в SMO Ojects.В Sqlserver я получаю это сообщение об ошибке

 Msg 121, Level 15, State 1, Procedure test_sp_syntaxtext, Line 124
The select list for the INSERT statement contains more items than the insert list.
  

Но с помощью этого кода

 catch (Exception ex)
          {
           ErrorFlag = true;
           //ex.Source.ToString();
           e2dInsertAndGenerateErrorLog(ex.InnerException.Message.ToString(), FileName, "CHECKINAPPLY", PathName, "ErrorLog.Err");
          }
  

я получаю это

 The select list for the INSERT statement contains more items than the insert list.
  

Мне также нужно кэшировать эту строку

 Msg 121, Level 15, State 1, Procedure test_sp_syntaxtext, Line 124
  

Есть предложения?

Редактировать:

   StreamReader str = new StreamReader(FiletextBox.Text.ToString());
  string script = str.ReadToEnd();
  str.Dispose();
  SqlConnection conn = new SqlConnection("Data Source=xx;database=xxx;User id=sx;Password=xxxx");
  Server server = new Server(new ServerConnection(conn));
  server.ConnectionContext.ExecuteNonQuery(script);
  

Комментарии:

1. Кажется, вы получаете InnerException что насчет сообщения об исполнении верхнего уровня тоже?

Ответ №1:

Используйте SQLException.

     catch (SqlException ex)
    {
        for (int i = 0; i < ex.Errors.Count; i  )
        {
            errorMessages.Append("Index #"   i   "n"  
                "Message: "   ex.Errors[i].Message   "n"  
                "LineNumber: "   ex.Errors[i].LineNumber   "n"  
                "Source: "   ex.Errors[i].Source   "n"  
                "Procedure: "   ex.Errors[i].Procedure   "n");
        }
        Console.WriteLine(errorMessages.ToString());
    }
  

Комментарии:

1. посмотрите на мой раздел редактирования, поскольку это исключение sqlexception не будет перехвачено, поскольку возникает ошибка ExecutionFailureException.

2. Исключение ExecutionFailureException возникает, когда при подключении к серверу возникает сбой выполнения.

3. Вам нравится обрабатывать это или исправлять здесь?

4. «Исключение возникло при выполнении инструкции Transact-SQL или пакета». —> это сообщение об ошибке, которое я получаю

5. но я хочу перехватить точное выполнение sql, происходящее в моем окне sql-запроса, как «Сообщение 121, уровень 15, состояние 1, Процедура test_sp_syntaxtext, строка 124 Список выбора для инструкции INSERT содержит больше элементов, чем список insert. Количество выбранных значений должно соответствовать количеству вставляемых столбцов. »

Ответ №2:

 catch (SqlException ex) { ... }
  

Комментарии:

1. посмотрите на мой раздел редактирования для этого sqlexception не будет перехвачено, поскольку возникает ошибка ExecutionFailureException

Ответ №3:

Взгляните на свойства, которые вы найдете наhttp://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlexception.aspx

Вам нужно будет перехватить SqlException вместо просто любого исключения.

Ответ №4:

При регистрации исключения рекомендуется регистрировать все это целиком, особенно stacktrace. Трассировка стека является наиболее важной частью. Если вы просто войдете в систему ex.ToString() , вы не будете отбрасывать эту информацию.

Ответ №5:

Попробуйте

catch (SqlException ex) { } вместо catch (Exception ex) { } .

Взгляните на информацию о SQLException в MSDN.

Ответ №6:

Я снова очень опаздываю, но ни один из ответов не кажется мне правильным. Контекст операции — SMO. С помощью SMO, SqlException могут быть инкапсулированы как внутренние исключения ExecutionFailureException. Вот почему он смотрит на InnerException .

Вот решение, которое я использую для регистрации SqlException сведений, если таковые имеются (при Logger наличии log4net ILog ).

Блок Catch:

 catch (Exception ex)
{
    Logger.Error("Unhandled error", ex);
    LogSqlErrors(ex);
}
  

LogSqlErrors (обратите внимание на последнюю строку, это то, что обрабатывает внутреннее исключение):

 private static void LogSqlErrors(Exception ex)
{
    if (ex == null)
        return;

    var sqlEx = ex as SqlException;
    if (sqlEx != null amp;amp; sqlEx.Errors != null amp;amp; sqlEx.Errors.Count > 0)
    {
        var sqlErrs = new StringBuilder();
        sqlErrs.AppendFormat("SqlException contains {0} SQL error(s):", sqlEx.Errors.Count)
            .AppendLine();
        foreach (SqlError err in sqlEx.Errors)
        {
            sqlErrs.AppendLine("--------------------------------")
                .AppendFormat("Msg {0}, Level {1}, State {2}, Procedure '{4}', Line {5}",
                    err.Number, err.Class, err.State, err.Procedure, err.LineNumber)
                .AppendLine()
                .AppendLine(err.Message);
        }
        Logger.Warn(sqlErrs.ToString());
    }

    LogSqlErrors(ex.InnerException);
}
  

К сожалению, если ваша строка команд sql содержит много пакетов (с использованием go разделителей, поддерживаемых SMO), это не подскажет вам, какой пакет sql выдает ошибку. (Номер строки ошибки вычисляется для неудачного пакета без учета количества строк в предыдущих пакетах.)

Я проверил способ ExecutionFailureException сборки (используя декомпилятор в SMO версии 12): он мог бы сохранить эту информацию, но это не так. Итак, вы можете только догадываться.

Более того, если вы используете ContinueOnError опцию, ошибки проглатываются (нигде не сохраняются). Что ж, было бы здорово, если бы команда SMO могла улучшить обработку исключений в своей библиотеке.