Как вы ловите исключения с «использованием» в C # - PullRequest
29 голосов
/ 06 февраля 2009

Учитывая этот код:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
}

Я привык писать блоки try / catch / finally для моего доступа к данным, однако меня подвергают «использованию», что кажется гораздо более простым способом сделать это. Однако я пытаюсь выяснить, как отлавливать исключения, которые могут возникнуть.

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

Отредактировано, чтобы добавить:

Меня убеждают, что «использование» заменяет мои блоки try / catch / finally. Я понимаю, что использование не ловит исключения. Так как же это замена?

Ответы [ 6 ]

57 голосов
/ 06 февраля 2009

using не предназначен для ловли исключений; он разработан, чтобы дать вам простой способ обернуть try / finally вокруг объекта, который необходимо утилизировать. Если вам нужно перехватить и обработать исключения, вам нужно расширить их до полного try / catch / finally или поместить вокруг него try / catch.


Чтобы ответить на ваши изменения (это using замена для try / catch / finally?), Тогда нет, это не так. В большинстве случаев, когда вы используете одноразовый ресурс, вы не собираетесь обрабатывать исключение, потому что обычно ничего полезного вы не можете сделать. Таким образом, он обеспечивает удобный способ очистки ресурса независимо от того, что вы пытаетесь сделать, работает или нет.

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

12 голосов
/ 06 февраля 2009
using (var cmd = new SqlCommand("SELECT * FROM Customers"))
{
    cmd.CommandTimeout = 60000;
    ...
}

является синтаксическим сахаром для

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}

Поэтому, когда люди говорят вам, что «использование» является заменой для try / catch / finally, они подразумевают, что вы должны использовать длинную форму, но добавить в свой блок catch:

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}
11 голосов
/ 06 февраля 2009

Оберните все операторы использования в try / catch. Как и все остальные, использование предназначено для очистки классов, реализующих интерфейс IDisposable

try
{

 using (var conn = new SqlConnection("..."))
 {
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
 }
}
catch(Exception ex)
{
//Handle, log, rethrow exception
}
7 голосов
/ 06 февраля 2009

Если вы хотите перехватывать исключения, вам, вероятно, следует вернуться к использованию try / catch / finally. Просто поместите вызовы .Dispose () в блок finally.

6 голосов
/ 06 февраля 2009

Использование операторов не имеет ничего общего с исключениями. Использование блоков просто гарантирует, что Dispose вызывается для объекта в блоке using, когда он выходит из этого блока. То есть:

using(SqlConnection conn = new SqlConnection(conStr))
{
   //use conn
}//Dispose is called here on conn.

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

3 голосов
/ 06 февраля 2009

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

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

using (SqlConnection conn = new SqlConnection(...))
{
    // do your db work here
    // whatever happens the connection will be safely disposed
}

Если вы хотите перехватить исключение по какой-либо другой причине, вы все равно можете сделать это:

try
{
    using (SqlConnection conn = new SqlConnection(...))
    {
        // do your db work here
        // whatever happens the connection will be safely disposed
    }
}
catch (Exception ex)
{
    // do your stuff here (eg, logging)
    // nb: the connection will already have been disposed at this point
}
finally
{
    // if you need it
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...