【问题标题】:When to log errors in ASPX when using database connections?使用数据库连接时何时在 ASPX 中记录错误?
【发布时间】:2010-12-03 04:49:56
【问题描述】:

使用数据库连接时何时在 ASPX 中记录错误? 在以下代码中,Pro ASP.NET 3.5 in C# 2008(第三版)的作者建议在 catch 块中记录 SQL 错误。我的问题是:

这是常见的做法吗?

这是最佳做法吗?

简而言之,关闭当前连接并完全分开处理错误会更好吗?这两种方法的优缺点是什么?

编辑添加:为了澄清问题不是应该记录(该问题已在其他地方讨论过),这个问题更具体。问题是在代码中记录的位置。应该在 catch 中完成(当连接仍然打开时)还是应该关闭当前连接并完全分开记录?不是将日志记录作为捕获的一部分添加的部分(即使它调用外部方法,该连接仍保持打开状态),直到它返回并到达“finally”。

    public int InsertEmployee(EmployeeDetails emp)
    {
        SqlConnection con = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand("InsertEmployee", con);
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10));
        cmd.Parameters["@FirstName"].Value = emp.FirstName;
        cmd.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20));
        cmd.Parameters["@LastName"].Value = emp.LastName;
        cmd.Parameters.Add(new SqlParameter("@TitleOfCourtesy", SqlDbType.NVarChar, 25));
        cmd.Parameters["@TitleOfCourtesy"].Value = emp.TitleOfCourtesy;
        cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
        cmd.Parameters["@EmployeeID"].Direction = ParameterDirection.Output;

        try 
        {
            con.Open();
            cmd.ExecuteNonQuery();
            return (int)cmd.Parameters["@EmployeeID"].Value;
        }
        catch (SqlException err) 
        {
            // Replace the error with something less specific.
            // You could also log the error now.
            throw new ApplicationException("Data error.");
        }
        finally 
        {
            con.Close();            
        }
    }

【问题讨论】:

  • 一般来说,你永远不应该在 catch 块中使用“throw new”。如果您想捕捉、记录和重新抛出,只需使用“throw;”。否则,您的代码看起来不错。

标签: asp.net sql exception-handling


【解决方案1】:

简短的回答:这取决于...

长答案:

只有在有人检查日志时才真正重要。如果这是一个个人网站,那么您可能不会太在意。但是,如果这是一个关键任务应用程序,那么您应该记录尽可能多的错误。错误日志不仅通过显示您在代码中发生错误来提供帮助调试的信息,而且日志还可以显示错误是否发生在一天中的特定时间(可能与另一个进程冲突)。但是,您需要记住记录小错误所涉及的额外开销。有时,根据问题的轻微程度,可以只向用户显示错误并让他们决定是否有足够大的问题与您联系。

我个人通过电子邮件向我发送了未处理的异常。使用 Page_Error 事件处理程序非常容易使用 ASP.NET 应用程序。

protected void Page_Error(object sender, EventArgs e)
{
    //Handle Error Here
}

我捕获的超时异常和其他异常通常会记录到某个数据库并永久保存。我通常将平凡的错误和成功审计记录到一个文本文件中,保存一个月左右。

希望这会有所帮助。

更新: 我想我现在更好地理解了你的问题。要在连接打开时登录catch,还是在连接关闭后登录?如果您在关闭连接后登录,您可能会获得更好的性能。但是,我认为简单的逻辑和可读性值得权衡登录您的 catch 并在 finally 中关闭连接。

【讨论】:

  • 感谢您的更新。它有助于澄清事情。在考虑了这一点之后,我现在假设如果代码在服务器上运行,那么命中可能还不够重要。也给你一个赞成票。
  • 谢谢。我同意,性能提升可能可以忽略不计。即使在性能方面,我也倾向于倾向于可读性/可维护性。并不是说我不关心性能,我关心。但有时这种权衡是值得的。祝你好运。
【解决方案2】:

恕我直言,这是个坏建议。

假设您使用的是原始 ADO.NET,您应该将 IDisposable 对象(如 IDbConnection)包装在 using 块中。

如果发生意外异常(即您无能为力),请不要捕获它并让诸如 ELMAH 之类的错误处理程序处理记录它。

【讨论】:

    【解决方案3】:

    我通常采用“包罗万象”的方法并记录任何真正异常的异常,然后吞下其余的。 :)

    编辑:

    我想我需要让自己更清楚......异常的经验法则是记录所有异常,除非在那些需要捕获异常的情况下。

    例子:

    在 .NET 1.1 中,唯一具有 TryParse() 的数据类型是 Double。因此,对于其他数据类型(例如 int),这样做是有意义的:

    try{
        int.Parse(x)
    } catch (FormatException){
        //take care of invalid input
    }
    

    我建议NLog。很棒的日志库。

    【讨论】:

    • 吞下异常是不好的坏习惯:google.com/search?hl=en&q=swallowing+exceptions
    • @Mauricio 仅供参考,这些搜索结果中的第一篇文章讨论了如何在某些情况下适合吞下异常。请删除 -1 :)
    • 不,我仍然认为这里不是吞下异常的地方。
    • @Mauricio 您没有正确阅读我的答案。我正在指示他记录异常。
    • 是的,我确实明白你的回答,但我不同意。
    【解决方案4】:

    要实现关注点分离,您需要从该方法中提取错误处理。有 3 种方法可以做到这一点:

    1)(最不优雅)使用两种方法:

    public void InsertEmployee(EmployeeDetails emp)
    {
        ...
    }
    
    public void TryInsertEmployee(EmployeeDetails emp)
    {
        try
        {
            InsertEmployee(emp);
        }
        catch (Exception e)
        {
            logger.Error(e);
            throw new ApplicationException("Data error.");
        }
    }
    

    2) 使用装饰器模式。

    public class ErrorHandlingEmployeeGateway
    {
        ...
    }
    

    3) 使用 AOP

    [LogException]
    public void InsertEmployee(EmployeeDetails emp)
    {
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-16
      • 1970-01-01
      • 2013-08-16
      • 2021-01-05
      • 2022-01-23
      • 2017-04-04
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多