我有一个记录器,记录我们内部应用程序的异常信息。
当我们记录SQL异常时,如果我们能够看到导致异常的实际查询,那么它将非常有用。
我们有办法实现这个目标吗?
答案 0 :(得分:16)
SqlException
没有引用导致异常的SqlCommand
。在您的记录器中无法执行此操作。您可以做的是在执行SqlCommand
的方法中捕获SqlException并将其包装在更具描述性的异常中。例如:
using (var command = new SqlCommand(connection, "dbo.MyProc"))
{
try
{
command.Execute();
}
catch (DbException ex)
{
throw new InvalidOperationException(ex.Message + " - " + command.Text, ex);
}
}
通过这种方式,您可以记录这个更具表现力的异常。
答案 1 :(得分:2)
你不能抛出一个sql异常。我认为他打算抛出一个包含command.CommandText的新Exception。
答案 2 :(得分:0)
作为一个简单的技巧,您还可以将sql作为异常数据的一部分添加。这将保留原始异常,但还会提供其他sql消息。
using (var command = new SqlCommand(connection, "dbo.MyProc"))
{
try
{
command.Execute();
}
catch (SqlException ex)
{
ex.Data.Add("Sql",command.Text);
throw ex
}
}
答案 3 :(得分:-1)
执行此操作的DRYest方法是编写一个辅助方法,该方法接受委托,sql命令文本以及可选的sql参数数组(如果使用参数化查询)。将委托包装在try catch块中,并在出现异常时调用LogError方法:
protected virtual TResult ExecuteAndLogError<TResult>(Func<TResult> code, string sql, SqlParameterCollection parameters = null)
{
try {
if ((System.Diagnostics.Debugger.IsAttached))
PrintSqlToDebug(sql, parameters);
return code();
} catch (Exception ex) {
LogError(sql, parameters, ex);
throw;
}
}
在我的SQL代码中,我从数据层帮助器方法调用ExecuteAndLogError。所有数据层方法都调用ExecuteAndLogError,因此只有一段代码可以记录SQL错误。
public virtual DataTable ExecuteDataTable(SqlCommand command, params SqlParameter[] parameters)
{
command.Parameters.AddRange(parameters);
DataTable table = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) {
using (command) {
ExecuteAndLogError(() => adapter.Fill(table), command.CommandText, command.Parameters);
}
}
return table;
}
您可以像这样使用它:repo.ExecuteDataTable("SELECT * FROM Users");
如果有异常,您可以实现LogError方法来执行其他日志记录。
部分代码来自Subtext Blog数据层类。