【问题标题】:Obtain the Query/CommandText that caused a SQLException获取导致 SQLException 的 Query/CommandText
【发布时间】:2010-06-03 10:01:05
【问题描述】:

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

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

有什么方法可以实现吗?

【问题讨论】:

    标签: c# sqlexception


    【解决方案1】:

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

    using (var command = new SqlCommand(connection, "dbo.MyProc"))
    {
       try
       {
          command.Execute();
       }
       catch (SqlException ex)
       {
          ex.Data.Add("Sql",command.Text);
          throw ex
       }
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 这种方式会丢失原始异常的堆栈跟踪吗?
        • 否,因为新异常包装了旧异常。
        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多