Я поймал исключение! Что теперь? - PullRequest
69 голосов
/ 08 апреля 2010

Я начал использовать блоки 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

Ответы [ 16 ]

64 голосов
/ 08 апреля 2010

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

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

23 голосов
/ 08 апреля 2010

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

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

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

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

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

20 голосов
/ 08 апреля 2010

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

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

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

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

14 голосов
/ 08 апреля 2010

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

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 () задокументирована как открывающая соединение при необходимости, и блок Using будет абсолютно уверен, что он правильно закрыт, , даже если выброшено исключение .

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

Фактически, именно эта способность исключений «всплывать» в вашем коде делает их такими ценными. Если вы всегда ловите исключение прямо там, где оно генерируется, то исключения не добавляют большого значения, кроме старого синтаксиса vb «При ошибке Перейти к X».

9 голосов
/ 08 апреля 2010

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

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

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

5 голосов
/ 08 апреля 2010

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

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

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

2 голосов
/ 08 апреля 2010

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

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

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

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

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

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

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

HTH!

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

2 голосов
/ 08 апреля 2010

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

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

2 голосов
/ 08 апреля 2010

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

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

1 голос
/ 08 апреля 2010

К вашему сведению, вам не нужно использовать улов, чтобы получить оператор finally.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...