何时在使用数据库连接时记录ASPX中的错误? 在下面的代码中,C#2008(第三版)中的Pro ASP.NET 3.5的作者建议在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();
}
}
答案 0 :(得分:0)
我通常采用“全能”的方法并记录任何非常特殊的例外情况,并吞下其余部分。 :)
编辑:
我想我需要让自己更清楚......例外的经验法则是记录任何和所有异常,除非在那些捕获异常有意义的情况下。
示例:
在.NET 1.1中,唯一具有TryParse()的数据类型是Double。因此,对于其他数据类型(例如int),执行此操作是有意义的:
try{
int.Parse(x)
} catch (FormatException){
//take care of invalid input
}
我建议NLog。神奇的伐木图书馆。
答案 1 :(得分:0)
恕我直言,这是一个不好的建议。
假设您正在使用原始ADO.NET,则应将IDisposable
个对象(如IDbConnection
)包装在using块中。
如果出现意外异常(即你无法做任何事情),请不要抓住它,让像ELMAH这样的错误处理程序处理它。
答案 2 :(得分:0)
简短回答:这取决于......
答案很长:
仅当有人检查日志时,记录才真正重要。如果这是个人网站,那么您可能并不在意。但是,如果这是一个关键任务应用程序,那么您应该记录尽可能多的错误。错误日志不仅通过显示错误发生的代码来提供帮助调试的信息,而且日志还可以显示错误是否发生在特定时间(可能与另一个进程冲突)。但是,您需要记住记录小错误所涉及的额外开销。有时,根据次要程度的不同,向用户显示错误并让他们决定是否与您联系是否足够大可能是可以的。
我个人通过电子邮件向我发送未经处理的例外情况。使用Page_Error事件处理程序很容易使用ASP.NET应用程序。
protected void Page_Error(object sender, EventArgs e)
{
//Handle Error Here
}
超时异常和我捕获的其他异常我通常会在某个地方登录数据库并永远保留。我通常会将普通错误和成功审核记录到我保留一个月左右的文本文件中。
希望这有帮助。
<强>更新强> 我想我现在更了解你的问题。要在连接打开时登录catch,还是在连接关闭后登录?如果在关闭连接后进行登录,则可能会有更好的性能。但是,我认为简单的逻辑和可读性值得在您的catch中登录并在finally中关闭连接。
答案 3 :(得分:0)
要实现关注点分离,您需要从该方法中提取错误处理。有三种方法可以做到:
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)
{
...
}