问题 获取导致SQLException的Query / CommandText


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

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

有没有办法实现这个目标?


9341
2018-06-03 10:01


起源



答案:


SqlException 没有参考 SqlCommand 这引起了例外。在您的记录器中无法执行此操作。你可以做的是在执行的方法中捕获SqlException SqlCommand 并将其包装在更具描述性的异常中。例:

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

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


11
2018-06-03 10:05



这种方式会失去原始异常的堆栈痕迹吗? - Cuong Le
不,因为新的异常包装了旧的异常。 - Steven


答案:


SqlException 没有参考 SqlCommand 这引起了例外。在您的记录器中无法执行此操作。你可以做的是在执行的方法中捕获SqlException SqlCommand 并将其包装在更具描述性的异常中。例:

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

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


11
2018-06-03 10:05



这种方式会失去原始异常的堆栈痕迹吗? - Cuong Le
不,因为新的异常包装了旧的异常。 - Steven


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


2
2018-06-14 14:51





执行此操作的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数据层类。


0
2017-09-19 21:22