Подтвердить что ты не робот

Как вы поймаете исключения с "использованием" в С#

С учетом этого кода:

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. Я понимаю, что использование исключает исключения. Итак, как это замена?

4b9b3361

Ответ 1

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


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

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

Ответ 2

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/, наконец, они подразумевают, что вы должны использовать длинную форму, но добавить в свой блок catch:

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}

Ответ 3

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

Ответ 4

Оберните все используемые операторы в 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
}

Ответ 5

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

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

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

Ответ 6

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

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

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
}