获取导致SQLException的查询/命令文本

15

我有一个记录公司应用程序异常信息的日志器。

当我们记录 SQL 异常时,如果能够看到导致异常的实际查询语句,那将非常有用。

有没有办法实现这一点?

4个回答

18

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);
    }
}

通过这种方式,您可以记录更具表现力的异常。


这种方式会丢失原始异常的堆栈跟踪吗? - cuongle
2
不行,因为新的异常包装了旧的异常。 - Steven

3

您不能抛出SQL异常。我认为他的意思是抛出一个包含command.CommandText的新异常。


2
作为一个简单的技巧,您也可以将sql作为异常数据的一部分添加。这将保留原始异常,但也提供了额外的sql消息。
using (var command = new SqlCommand(connection, "dbo.MyProc"))
{
   try
   {
      command.Execute();
   }
   catch (SqlException ex)
   {
      ex.Data.Add("Sql",command.Text);
      throw ex
   }
}

-1
最DRY的方法是编写一个辅助方法,该方法接受一个委托、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博客数据层类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接