попытаться поймать каждое соединение БД? - PullRequest
7 голосов
/ 13 января 2011

Рекомендуется ли устанавливать блок try-catch в каждую функцию, которая открывает соединение с БД и регистрирует там ошибку, или мне лучше отлавливать ошибки на более высоком уровне приложения?

public static Category GetCategoryByName(string name)
{
    Category result;
    try
    {
        using (IDbConnection conn = ConnectionHelper.CreateDbConnectionByName(_connectionStringName))
        {
            conn.Open();
            using (IDbCommand cmd = conn.CreateCommand())
            {
                //do stuff
            }
        }
    }
    catch(Exception e)
    {
         // log error here?
    }
    return result;
}

или, скорее,

try
{
    Category myCat = DataTools.GetCategoryByName("myCat");
    // other stuff
}
catch(Exception e)
{
   // log error here?
}

Подводя итог: следует ли обнаруживать ошибки как можно раньше в коде?Или мне лучше поймать их там, где у меня есть больше информации о контексте?

Ответы [ 4 ]

13 голосов
/ 13 января 2011

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

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

6 голосов
/ 13 января 2011

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

После того, как вы извлечете и зарегистрируете все, что релевантно, сбросьте исключение или поместите его в менее конкретное исключение, такое как InvalidDataException или Exception, и выбросьте его.Затем вы можете перехватить эти более общие исключения на более высоких уровнях.

try
{
    // Execute DB call here
}
catch(SqlException exp)
{
    // Log what you need from here.
    throw new InvalidOperationException("Data could not be read", exp);
}

Когда вы вызываете этот метод с более высокого уровня, вы можете просто перехватить InvalidOperationException.Если для более высоких уровней требуется больше подробностей, InnerException предоставит SqlException, к которому можно получить доступ.

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

0 голосов
/ 13 января 2011

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

Я использовал это и раньше:

<code>
try
{
   DB Command
}
catch (Exception ex)
{
   Log(ex)
   throw; //preserve stacktrace
}
0 голосов
/ 13 января 2011

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

  • повторно вызвать исключение?
  • выбросить другое (более общее) исключение?
  • вернуть нулевое значение вызывающей стороне?
...