【问题标题】:try-catch every db connection?尝试捕获每个数据库连接?
【发布时间】:2011-06-08 12:38:37
【问题描述】:

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

总结一下:是否应该尽早在代码中发现错误?还是我应该在我有更多关于上下文的信息时抓住它们?

【问题讨论】:

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


    【解决方案1】:

    与往常一样,这取决于,但一般来说,只有在您可以对其采取措施或您有特定代码(例如重试)要发生时才捕获异常,否则,让异常冒泡并进入最顶层可以集中记录/处理它。

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

    【讨论】:

      【解决方案2】:

      在捕获异常时,始终尽量使用最准确的异常。例如,在使用 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。

      我遵循的异常处理的一般方法是只捕获我可以有效采取行动的内容。在代码的较低级别捕获真正的一般异常没有意义,因为您真的可以期望 everything 出错或能够从每个异常中恢复,例如OutOfMemoryException 或 StackOverflowException。

      【讨论】:

        【解决方案3】:

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

        我以前也用过这个:

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

        【讨论】:

          【解决方案4】:

          我更喜欢第一种方法,但你仍然需要弄清楚在 catch 块中还能做什么......

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

          【讨论】:

            猜你喜欢
            • 2021-10-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-25
            • 1970-01-01
            • 2012-02-18
            相关资源
            最近更新 更多