Правильное соглашение об использовании / try / catches - PullRequest
0 голосов
/ 30 октября 2011

Давайте предположим, что я получил этот код:

internal static bool WriteTransaction(string command)
{
    using (SqlConnection conn = new SqlConnection(SqlConnectionString))
    {
        try
        {
            conn.Open();

            using (SqlCommand cmd = new SqlCommand(command, conn))
               cmd.ExecuteNonQuery();
        }
        catch { return false; }
    }

    return true;
}

Ну, я поместил using коннекта вне предложения try / catch, потому что конструктор SqlConnection не будет выдавать никаких исключений (как говорится). Поэтому в предложении содержится conn.Open(), поскольку оно может выдавать некоторые исключения.

Теперь, это правильный подход к кодированию? Посмотрите: конструктор SqlCommand также не генерирует исключения, но для сокращения кода я поместил его вместе с cmd.ExecuteNonQuery() в оба элемента try / catch.

Или,

может быть, этот должен быть вместо этого?

internal static bool WriteTransaction(string command)
{
    using (SqlConnection conn = new SqlConnection(SqlConnectionString))
    {
        try { conn.Open(); }
        catch { return false; }

        using (SqlCommand cmd = new SqlCommand(command, conn))
            try { cmd.ExecuteNonQuery(); }
            catch { return false; }
    }

    return true;
}

(простите за мой английский)

Ответы [ 6 ]

1 голос
/ 30 октября 2011

Ваш первый пример кода с одним блоком try-catch эквивалентен второму. Первый, однако, легче читать и короче.


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

Хорошо написанная ссылка на это здесь: http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx.

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

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

1 голос
/ 30 октября 2011

Если вы не можете обработать исключение каким-либо осмысленным образом, не улавливайте его.Скорее, пусть он распространяется по стеку вызовов.

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

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

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

[Кстати, WriteTransaction(), вероятно, плохое название для этого метода, учитывая код, который вы показали.]

0 голосов
/ 30 октября 2011

Учитывая, что ваш метод WriteTransaction поглощает все исключения и возвращает успешное завершение транзакции, или нет, я бы использовал один блок try / catch для всего метода.

internal static bool WriteTransaction(string command) {
    try {
        using (SqlConnection conn = new SqlConnection(SqlConnectionString)) {
            conn.Open();

            using (SqlCommand cmd = new SqlCommand(command, conn)) {
                cmd.ExecuteNonQuery();
            }
        }
    }
    catch { 
        return false; 
    }
    return true;
}

Теперь вы должны спросить себя, правильно ли перехватывать все исключения и возвращать true / false. Когда вы будете работать, как вы собираетесь диагностировать и исправлять ошибки, если вы хотя бы не зарегистрировали исключение?

0 голосов
/ 30 октября 2011

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

Иногда это так же просто, как считатьстроки кода; -) ...

HTH!

PS У меня не было бы оператора try/catch в этом методе вообще, но я бы поместил его на более высокий уровеньгде этот внутренний метод вызывается.

0 голосов
/ 30 октября 2011

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

0 голосов
/ 30 октября 2011

с хорошим предложением catch (ведение журнала исключений) вам действительно не нужен блок 2x try, достаточно 1

... ваш второй подход неверен - есть нет нужно try catch открывать соединение - потому что даже если вы поймете, что все готово - вы не можете выполнить запрос.В вашем блоке catch вы можете попытаться «исправить» эту проблему, но что это даст вам - циклы while в catch?

...