【发布时间】:2022-01-24 17:16:03
【问题描述】:
我有一个方法UpdateSQL(),它可能由于两个或多个不同的不相关原因引发相同类型的异常 (SqlException)。原因 1 = 执行 sqlConn.open() 时出现“无效的连接字符串”。原因 2 = 执行 sqlCommand.ExecuteNonQuery() 时出现“执行存储过程时出错”。如何确定在调用方方法中引发 SqlException 的原因,以便我可以记录自定义原因?
调用方法
try
{
UpdateSQL();
}
catch(SqlException e)
{
// How do i know the reason for which exception was thrown so I could log
log.LogError(e, "Reason");
}
更新方法-
UpdateSQL()
{
using (var sqlConn = new SqlConnection("myConnString"))
{
sqlConn.Open(); // May throw exception for reason 1
SqlCommand sqlCommand = new SqlCommand("myStoredProcedure", sqlConn);
sqlCommand.CommandType = CommandType.StoredProcedure;
// Some random parameter
SqlParameter myParam = sqlCommand.Parameters.AddWithValue("@Time", "3/10/2015 2:15:10 AM");
myParam.SqlDbType = SqlDbType.NVarChar;
sqlCommand.ExecuteNonQuery(); // May throw exception for reason 2
}
}
我可以看到的一种可能方法是,在 Update 方法中将两个 Sql 命令本身包装在单独的 try-catch 块中。但是有没有办法避免这种情况?
【问题讨论】:
-
我认为正是出于这个原因,通常会有只抛出专有异常的策略(即,将捕获的所有内容包装起来,然后作为自己的东西重新抛出)。这样您就可以封装供应商依赖项。也就是说,每个 sql 异常中都有信息:状态、消息和供应商特定的错误代码,它们可以帮助您找出要做什么。此外,SqlExceptions 是(或可以是)链式的,也就是说,
geNextException()可能返回非 null,可能指向底层或结果错误。 -
以编程方式检查 e.Message 在任何情况下通常都不是一个好方法。 ErrorCode 似乎是一个值得探索的好主意。
-
..您可能最好记录并呈现给人类,而不是试图过多地参与处理它们和修复代码。综上所述,同意其他人的观点,对于 SQLExceptions,每个都有一个数字代码来描述错误的种类,你可以做一些事情来指导你的用户
-
这可能会有所帮助。 IMO 太复杂了,但是有一些数字和内部异常可以提供更具体的信息。 stackoverflow.com/questions/18894345/…
-
判断异常是打开连接还是执行查询的方法是查看堆栈跟踪,而不是在日志中编写自定义消息来描述可能抛出的每个操作,以便您知道如何找到引发异常的代码行。这正是堆栈跟踪向您展示的内容。