14

我有一个记录器,用于记录我们内部应用程序的异常信息。

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

有没有办法我们可以做到这一点?

4

4 回答 4

18

SqlException不包含对SqlCommand导致异常的引用。在您的记录器中没有办法做到这一点。您可以做的是在执行的方法中捕获 SqlExceptionSqlCommand并将其包装在更具描述性的异常中。例子:

using (var command = new SqlCommand(connection, "dbo.MyProc"))
{
    try
    {
        command.Execute();
    }
    catch (DbException ex)
    {
        throw new InvalidOperationException(ex.Message + " - " + command.Text, ex);
    }
}

这样您就可以记录这个更具表现力的异常。

于 2010-06-03T10:05:25.073 回答
3

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

于 2011-06-14T14:51:06.487 回答
1

作为一个简单的技巧,您还可以将 sql 添加为异常数据的一部分。这将保留原始异常,但也会提供额外的 sql 消息。

using (var command = new SqlCommand(connection, "dbo.MyProc"))
{
   try
   {
      command.Execute();
   }
   catch (SqlException ex)
   {
      ex.Data.Add("Sql",command.Text);
      throw ex
   }
}
于 2020-12-11T09:41:43.413 回答
-1

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

于 2011-09-19T21:22:47.083 回答