【问题标题】:Logging parameterized SQL query with parameters included记录包含参数的参数化 SQL 查询
【发布时间】:2013-06-01 10:20:26
【问题描述】:

我有几个函数接受 SQL 查询(已添加参数)并针对数据库运行它。当 SQL 查询失败时,我想记录完整的查询,包括参数,以便准确查看导致失败的原因。 query.ToString() 返回 IBM.Data.Informix.IfxCommand,所以目前我只是捕获 query.CommandText,但如果参数是导致问题的原因,这并不能准确地告诉我我正在处理什么。

这是我正在使用的查询函数之一:

public DataTable CallDtQuery(IfxCommand query)
{
  DataTable dt = new DataTable();
  using (IBM.Data.Informix.IfxConnection conn = new IfxConnection(sqlConnection))
  {
    try
    {
      IBM.Data.Informix.IfxDataAdapter adapter = new IfxDataAdapter();
      query.Connection = conn;
      conn.Open();
      adapter.SelectCommand = new IfxCommand("SET ISOLATION TO DIRTY READ", conn);
      adapter.SelectCommand.ExecuteNonQuery(); //Tells the program to wait in case of a lock.     
      adapter.SelectCommand = query;
      adapter.Fill(dt);
      conn.Close();
      adapter.Dispose();
      }
    catch (IBM.Data.Informix.IfxException ex)
    {
      LogError(ex, query.CommandText);
      SendErrorEmail(ex, query.CommandText);
      DisplayError();
    }
  }
  return dt;
}

这是日志功能:

private void LogError(IfxException ex, string query)
{ //Logs the error.
  string filename = HttpContext.Current.Server.MapPath("~") + "/Logs/sqlErrors.txt";
  System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Append);
  System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);

  sw.WriteLine("=======BEGIN ERROR LOG=======");
  sw.WriteLine(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString());
  sw.WriteLine("Query = " + query);
  sw.WriteLine("User = " + HttpContext.Current.Session["UserID"]);
  sw.WriteLine("Error Message = " + ex.Message);
  sw.WriteLine("Message Source:");
  sw.WriteLine(ex.Source);
  sw.WriteLine("=============================");
  sw.WriteLine("Message Target:");
  sw.WriteLine(ex.TargetSite);
  sw.WriteLine("=============================");
  sw.WriteLine("Stack Trace:");
  sw.WriteLine(ex.StackTrace);
  sw.WriteLine("========END ERROR LOG========");
  sw.WriteLine("");

  sw.Close();
  fs.Close();
}

有没有办法像我在这里一样传递整个字符串(包括参数)以进行日志记录?我发现唯一可行的方法是将查询传递给日志记录函数并构建一个 for 循环以将每个参数记录为单独的项目。由于其中一些查询有许多参数,而且我不会在一个简单的字符串中获得完整的查询,因此这并不是最理想的解决方案。

【问题讨论】:

    标签: c# asp.net sql informix


    【解决方案1】:

    怎么样:

    // ...
    catch (IBM.Data.Informix.IfxException ex)
    {
        LogError(ex, query);  // NOTE
        SendErrorEmail(ex, query.CommandText);
        DisplayError();
    }
    

    然后像这样创建一个重载:

    private void LogError(IfxException ex, IfxCommand query)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(String.Format("{0}\n", query.CommandText));
        foreach (IDataParameter parameter in query.Parameters)
            sb.Append(String.Format("\t{0} = {1}\n",
                parameter.ParameterName, parameter.Value));
    
        LogError(ex, sb.ToString());
    }
    

    【讨论】:

    • 这行得通,虽然我把它改了一点。我添加了更改作为答案,这样您就可以看到我做了什么。谢谢!
    • 我遇到了一种情况,我必须记录所有查询及其使用的值并遇到您的答案。好东西!!正是我想要的:i.imgur.com/Xqgl3et.png 谢谢鲁本斯 :)
    【解决方案2】:

    鲁本斯:

    由于我想将查询同时传递给 LogError 和 SendErrorEmail 函数,因此我为这种方法创建了一个独特的函数。我还调整了您的版本以自动替换参数点(例如,查询中的“cmt_slmno = ?”),而不是制作参数列表。结果如下:

    private string RecreateQuery(IfxCommand query)
    {
      StringBuilder sb = new StringBuilder();
      sb.Append(query.CommandText);
      foreach (IfxParameter parameter in query.Parameters)
        sb.Replace(" ? ", string.Format(" {0} ", parameter.Value.ToString()));
      return sb.ToString();
    }
    

    以及相应调整的catch语句:

    catch (IBM.Data.Informix.IfxException ex)
    {
      string errorQuery = RecreateQuery(query);
      LogError(ex, errorQuery);
      SendErrorEmail(ex, errorQuery);
      DisplayError();
    }
    

    这种方法有潜在的流氓问题?在文本中被替换,例如,如果语句在它试图设置的字符串中有一个问号。这对于我在这个应用程序中使用的数据来说应该是非常罕见的,并且用空格包围问号应该涵盖除用户输入的极其罕见的、格式奇特的字符串之外的所有内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 2012-11-18
      • 2019-06-08
      相关资源
      最近更新 更多