try-catch每个数据库连接?

时间:2011-01-13 14:00:32

标签: c# .net error-handling try-catch

是否建议在每个打开数据库连接的函数中放置一个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 个答案:

答案 0 :(得分:13)

与往常一样,它取决于,但一般情况下,如果您可以对其执行某些操作,或者您需要执行特定代码(例如重试),则只捕获异常,否则,让异常冒泡并且最顶层可以集中记录/处理它。

任何其他方式都会导致大量日志记录代码散布在所有业务逻辑中。

答案 1 :(得分:6)

捕获异常时,请尽量使用最准确的异常。例如,在使用SQL Server时,请捕获SqlException,因为它将包含有关exceptin的更多信息,而不是一般的Exception。您可以获得实际的行号和其他有用的诊断信息。

在解压缩并记录了所有相关内容之后,重新抛出异常或将其包装在不太具体的异常中,例如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。

答案 2 :(得分:0)

我更喜欢第一种方法,但是你还需要弄清楚我还能做些什么呢?

  • 重新抛出异常?
  • 抛出另一个(更一般的)异常?
  • 将null返回给调用者?

答案 3 :(得分:0)

我通常只处理UI中的异常,下面的所有内容我总是把它扔回顶层。这样,堆栈跟踪一直保持不变。你总是可以记录并扔掉它。

我之前也使用过这个:


try
{
   DB Command
}
catch (Exception ex)
{
   Log(ex)
   throw; //preserve stacktrace
}