Я поймал исключение !! Что теперь?

71

Я начал использовать блоки try catch (немного поздно, я знаю!), но теперь я не уверен, что делать с исключением, как только я его поймал. Что мне делать?

Try
    connection.Open()
    Dim sqlCmd As New SqlCommand("do some SQL", connection)
    Dim sqlDa As New SqlDataAdapter(sqlCmd)
    sqlDa.Fill(dt)
Catch ex As SQLException
    ' Ahhhh, what to do now!!!?
Finally
    connection.Close()
End Try
  • 0
    Кажется, вы чувствуете, что это обязательно добавить везде попробовать / поймать. Может быть, вы можете поделиться с нами тем, что вы знаете об этом утверждении, чтобы мы могли уточнить концепцию.
  • 72
    достаньте стеклянную банку и проткните несколько отверстий в крышке ;-)
Показать ещё 6 комментариев
Теги:
exception-handling

16 ответов

64

Правило большого пальца для обработки исключений - если вы не знаете, что с ним делать, не поймите его.

Корреляция в правиле большого пальца для обработки исключений - Обработка исключений в последний ответственный момент. Если вы не знаете, является ли это последним ответственным моментом, это не так.

  • 2
    Я не согласен с этим и отредактировал свой ответ, чтобы отразить почему.
  • 1
    +1 - и .. Если вы не можете сделать что-нибудь полезное здесь, не поймите это здесь.
Показать ещё 8 комментариев
23

Что вы хотите сделать? Это полностью зависит от вашего приложения.

Вы можете повторить попытку, вы можете отобразить на экране сообщение, записать в журнал, возможности бесконечны.

В качестве разработчика вы не можете предсказать все возможные ошибки. Это хорошая идея иметь общий код catch, даже если вы не знаете, как исправить ошибку. Вы можете сохранить базу данных, и может произойти одна из 50 ошибок базы данных, и вы не сможете писать код для обработки каждого из них.

Вы должны ввести общий улов, чтобы убедиться, что ваша программа не просто сбой, а в некоторых случаях просто отображение ошибки и предоставление им другого пути достаточно. Представьте, была ли причина "диск заполнен". Вы можете просто распечатать исключение и позволить пользователю повторить попытку - они будут знать, что делать, и решить проблему самостоятельно.

Вот почему я не согласен с комментарием о том, чтобы не обрабатывать его, если вы не знаете, что делать. Вы всегда должны обращаться с ним, даже если он просто отображает сообщение с сообщением "Ошибка", потому что оно бесконечно лучше, чем "Эта программа выполнила незаконную операцию и будет закрыта".

  • 0
    Я также рекомендовал бы уменьшить количество кода внутри вашего блока, особенно в приведенном выше примере. Вы а) подключаетесь к базе данных и б) выполняете команду SQL, и то и другое может вызвать много исключений. Поместите каждую в отдельную попытку (или проанализируйте вашу бывшую / исключительную ситуацию), чтобы у вас было лучшее представление о том, с какой ошибкой вы сталкиваетесь (вас ударили по глазу или ударили по ноге?)
  • 0
    Вы также можете закончить завершение приложения, так как исключение является фатальным
Показать ещё 9 комментариев
21

Это зависит от вашей бизнес-логики, но вы можете сделать одно или несколько из следующих.

  • Отменить транзакцию
  • Запишите ошибку
  • Оповестить любого пользователя приложения
  • Повторите операцию
  • Удалить исключение

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

Хорошая статья об обработке исключений VB.NET - Обработка исключений в VB.NET от Rajesh VS.

  • 0
    Я предлагаю как минимум три лучших для большинства ошибок SQL.
14

Я вижу много рекомендаций, чтобы не поймать его, если вы не знаете, что с ним делать. Это только что-то вроде права. Вы должны поймать исключения, но, возможно, не на этом уровне. Используя ваш код для примера, я бы написал его более как это:

Using connection As New SqlConnection("connection string here"), _
      sqlCmd As New SqlCommand("do some SQL", connection), _
      sqlDa As New SqlDataAdapter(sqlCmd)

    sqlDa.Fill(dt)
End Using

Не только нет Try/Catch/Наконец, нет открытого или закрытого. Функция .Fill() задокументирована как открытие соединения, если требуется, и блок "Использование" будет абсолютно уверен, что он закрыт правильно, даже если выбрано исключение.

Это дает вам возможность ловить исключения на более высоком уровне; в пользовательском интерфейсе или бизнес-коде вызывает функцию, в которой выполняется ваш запрос, а не прямо здесь, в самом запросе. Этот код более высокого уровня находится в гораздо лучшем положении для принятия решений о том, как действовать, что должно произойти в журнале или показать пользователю сообщение об ошибке.

На самом деле, эта способность исключений "пузырится" в вашем коде, что делает их настолько ценными. Если вы всегда поймаете исключение прямо там, где оно было выбрано, то исключения не добавляют большого значения за рамки старого синтаксиса "On Error Goto X".

9

Это зависит от того, что действительно делает sql. Это что-то:

  • что пользователь сделал? Возможно, создайте учетную запись или сообщение - тогда вам нужно сообщить пользователю, что что-то не так.
  • что приложение действительно? Как очистка журналов или что-то подобное? Это фатально? Может ли приложение продолжить? Это что-то, что можно игнорировать - возможно, повторилось? Должен ли администратор быть объявлен?

Начните с этих вопросов, они обычно приводят к ответам о том, как лечить исключения

5

Если вы не ожидали ошибки (API говорит, что это может произойти) и может справиться с ней (есть очевидный шаг, если возникает исключение), вы, вероятно, захотите сбой с большим количеством шума. Это должно произойти во время тестирования/отладки, так что ошибка может быть исправлена ​​до того, как пользователь ее увидит!

Конечно, как отмечают комментаторы, пользователь никогда не должен действительно видеть весь этот шум. Высокоуровневый try/catch или какой-либо другой метод (EMLAH, я слышу для веб-проектов .net) можно использовать, чтобы показать пользователю хорошее сообщение об ошибке ( "Ой, что-то пошло не так! Что вы пытались сделать?" ) с кнопкой отправки...

В основном, я хочу сказать следующее: Не ловить ошибки, о которых вы не знаете, как обращаться! (за исключением обработчика высокого уровня). Крах рано и с максимальной информацией. Это означает, что вы должны зарегистрировать стек вызовов и другую важную информацию, если это вообще возможно для отладки.

  • 3
    С другой стороны, никогда не сталкивайтесь с большим шумом на глазах пользователя. Скажите что-то вроде «Опс, что-то пошло не так, мы работаем над этим». Нет деталей, чтобы увидеть на публике.
  • 4
    Лучше всего отобразить пользовательскую страницу с текстовым полем «пожалуйста, сообщите нам, что вы делали» и нажмите кнопку «Отправить», чтобы они могли выйти. Конечно, не подключайте это ни к чему.
2

Я хотел бы предложить вам, что если вы не знаете, что делать с исключением, не поймите его. Слишком часто кодеры захватывают исключения и просто проглатывают их целиком.

catch (Exception ex)
{
  /* I don't know what to do.. *gulp!* */
}

Ясно, что это не хорошо, потому что происходят плохие вещи, и никаких действий не предпринимается. Исключайте только исключения, которые могут быть действительны!

Это говорит о том, что грациозная обработка ошибок важна. Не хотите, чтобы ваше приложение разбилось, не так ли? Вы можете найти ELMAH полезным для веб-приложений, а глобальный обработчик исключений довольно легко настроить для настольных приложений WinForms или XAML.

Объединяя все это, вы можете найти эту стратегию полезной: 1. поймать определенные исключения, которые, как вы знаете, могут произойти (DivideByZeroException, SQLException и т.д.) и избегать общего исключения Exception; 2. Повторно поднимите исключение после его обработки. например.

catch (SQLException ex)
{
  /* TODO: Log the error somewhere other than the database... */
  throw; // Rethrow while preserving the stack trace.
}

Что вы действительно можете сделать с SQLException? Удалось ли соединение с базой данных? Это был плохой запрос? Вероятно, вы не хотите добавлять для этого всю логику обработки, и, кроме того, что, если это то, чего вы не ожидали? Поэтому просто обработайте исключение, если можете, переподнять, если вы не уверены, что он разрешен и изящно обрабатываете его на уровне (например, покажите сообщение типа "Что-то пошло не так, но вы могли бы продолжить работу. Подробная информация:" [ex.Message] ". Abort или Retry?" )

НТН!

Джон Сондерс, спасибо за исправление.

  • 2
    Тщательная регистрация и повторный бросок. Если вы регистрируетесь на каждом уровне, вы можете получить много, много записей одного и того же исключения в вашем журнале ошибок. Google "log rethrow" за несколько советов по правильному пути.
  • 0
    @JohnSaunders Вы должны удалить свой комментарий сейчас, когда ответ был исправлен.
Показать ещё 1 комментарий
2

Следует иметь в виду, что в тех разделах, где вы чувствуете, что хотите использовать try/catch, вы должны перенести свои инструкции Dim из блока try. Вы можете назначить им значения внутри блока, но если вы определите их внутри блока try, у вас не будет доступа к этим переменным внутри секции catch, поскольку они будут недоступны в этой точке.

Моя стандартная практика в блоках catch, включая попытку исправления ошибки, если это возможно, заключается в том, чтобы выписать какой-либо механизм ведения журнала, я использую информацию о ключевых переменных, которые были вовлечены в раздел, вызывающий ошибку. Это не нужно, но я нашел, что это часто помогает при проблемах отладки.

2

Если вы не знаете, как реагировать на него, не поймайте исключение.

Поймайте его вместо этого в том месте, где у вас есть возможность обработать его, и где вы знаете, как продолжить выполнение впоследствии.

1

FYI, вам не нужно использовать catch для утверждения finally.

Иногда люди генерируют новое исключение, которое более firendly и добавляет исходное исключение в качестве внутреннего исключения.

Часто это используется для регистрации ошибки в файле или отправки электронной почты оператору.

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

1

Во-первых, если для приложения не существует способа обработать исключение, вы не должны его ловить (ведение журнала может выполняться с помощью обработчиков событий исключения без catch).

Если есть что-то, что вы можете сделать, сделайте это. Например, отмените транзакцию и сообщите об этом пользователю. Это будет зависеть от вашего приложения.

0

Ну, Это зависит в первую очередь, если вы делаете деньги из своей заявки или нет. По моему опыту, никто (кто заплатил за заявку) любит видеть, как он рушится и закрывается, вместо этого они предпочитают короткое и объяснительное сообщение об ошибке и второй шанс продолжить то, что они делают, плюс возможность сохранить/экспортировать измененные данные. ИМО - лучшая практика - поймать все, что может вызвать что-то неправильное из-под вашего контроля, например операции ввода-вывода, связанные с сетью задачи, e.t.c. и отобразить соответствующее сообщение пользователю. В случае, если исключение выбрано из-за ошибки, связанной с логикой, лучше не улавливать ее, поскольку это поможет вам найти и исправить фактическую ошибку.

Надеюсь, что это поможет.

0

В зависимости от типа приложения рассмотрите либо глобальный обработчик ведения журнала (т.е. "Application_Error" для приложений ASP.NET), либо используя предварительно построенный механизм обработки исключений с открытым исходным кодом или MSFT.

Блок приложений для обработки исключений как часть Enterprise Library 5.0 - предлагаемая структура для использования.

Помимо регистрации, я согласен с тем, что исключения не должны быть явно пойманы, если вам не нужно что-то делать с ними. И худшая ошибка - это просто "Поймать", а затем "Бросить", так как это помешает StackTrace.

0

Я бы подумал о регистрации, что произошло исключение, и уведомить пользователя о том, что вы не смогли выполнить свой запрос. Это предполагает, что этот запрос SQL необходим для завершения действия, которое пользователь пытается выполнить.

0

Все зависит от контекста. Возможные варианты: "Использовать данные по умолчанию вместо данных из базы данных" и "Отобразить сообщение об ошибке для пользователя".

0

Если вы не хотите ничего с этим делать, вы всегда можете просто попробовать/наконец, а затем попробовать/уловить/наконец

Ещё вопросы

Сообщество Overcoder
Наверх
Меню