找出哪个查询导致了异常

本文关键字:异常 查询 | 更新日期: 2023-09-27 18:08:09

我有一个OleDbCommand为我的插入,我试图实现以避免SQL注入。在此之前,我使用简单的字符串进行查询,我不喜欢这样。现在我插入记录的代码看起来像这样:

 try
 {
    OleDbConnection rConn = new OleDbConnection(args[3]);
    rConn.Open();
    using (OleDbCommand insert = new OleDbCommand(String.Format(Globals.QUERY_INSERT_CLICK, args[4]), rConn))
    {
        insert.Parameters.Add("id", OleDbType.BigInt, 20);
        insert.Parameters.Add("email", OleDbType.VarChar, 255);
        insert.Parameters.Add("clickTime", OleDbType.Date, 20);
        insert.Parameters.Add("subscriberId", OleDbType.BigInt, 20);
        insert.Parameters.Add("link", OleDbType.VarChar, 255);
        insert.Parameters.Add("sendQueueId", OleDbType.BigInt, 20);
        insert.Parameters.Add("mailingListName", OleDbType.VarChar, 255);
        insert.Parameters.Add("newsletterId", OleDbType.BigInt, 20);
        insert.Parameters.Add("sendDate", OleDbType.Date, 20);
        insert.Parameters[0].Value = clickitem.Id;
        insert.Parameters[1].Value = clickitem.Email;
        insert.Parameters[2].Value = clickitem.ClickTime;
        insert.Parameters[3].Value = clickitem.SubscriberId;
        insert.Parameters[4].Value = clickitem.Link;
        insert.Parameters[5].Value = clickitem.SendQueueId;
        insert.Parameters[6].Value = mailingListName;
        insert.Parameters[7].Value = newsletterID;
        insert.Parameters[8].Value = sendDate;
        insert.Prepare();
        insert.ExecuteNonQuery();
    }
    rConn.Close();
}
catch (OleDbException oldbex)
{
    logger.WriteToLog("GETCLICKS", "OleDbException: " + Globals.ERROR_INSERT_CLICK + oldbex.Message);
}
catch (Exception ex)
{
    logger.WriteToLog("GETCLICKS", Globals.ERROR_INSERT_CLICK + ex.Message);
}

我有成千上万的插入,我从我的日志中看到,其中一些没有正确插入。异常告诉我例如不能从bigint转换到datetime之类的东西。虽然我的大多数记录都被正确插入,但我想知道究竟是哪些插入查询导致了错误。我怎么才能算出来呢?

注意:在使用此方法之前,我可以访问我的查询字符串,我立即发现了错误。现在我猜我对SQL注入的免疫力对我自己造成了一些混乱

找出哪个查询导致了异常

既然您提到接收不同/多个数据转换错误,我的建议是在捕获oledbeexception时改进您的日志记录。

您可以在初始'GETCLICKS'日志条目之后将每个参数值写入日志。这将使您更好地了解来自用户的哪些值格式不正确。

标准SQL错误不会显示导致错误的列或值。

最简单的方法是将SQL语句和参数值添加到日志调用中。
string params = string.Join(Environment.NewLine,
                            insert.Parameters
                                  .Select(p => string.Format("{0} : {1}",
                                                             p.Name, 
                                                             p.Value))
                                  .ToArray()
                            );
string message = string.Format("{0}: {1}{2}'n{3}'n{4}",
                               "OleDbException: " ,
                               Globals.ERROR_INSERT_CLICK,
                               oldbex.Message,
                               insert.CommandText,
                               params);
logger.WriteToLog("GETCLICKS", message );

参数Value属性为Object泛型类型。它接受你分配给它的任何东西。当然,这不是处理数据的好方法。我将尝试将值转换为参数的适当数据类型,并避免向数据库发送虚假值。这样,您将在参数赋值时立即捕获错误,而不是在执行insert

时捕获错误。

例如:

insert.Parameters[2].Value = Convert.ToDateTime(clickitem.ClickTime);

如果这不是一个有效的日期时间,它将在转换时失败。在日志

困难的方式,但好的设计。我建议您通过继承Base exception类来创建自己的自定义异常类。

创建一个以oleddbcommand作为输入参数的构造函数,在那里您可以尝试记录oleddbcommand。通过循环遍历参数集合。如下例所示,SQLcommand(与OLedbCommand大致相同)

或Easy Way—当抛出异常时,写入OLDEBCommand。

下面是我为SQL命令的StoredProcExecutionException创建的示例。你可以为OleDbCommand完全复制这个。希望能有所帮助

 public StoredProcExecutionException(string message, Exception innerException ,SqlCommand sqlCommand)
            : base(Convert.ToString(sqlCommand.CommandType ,CultureInfo.InvariantCulture)+" : "
                + Convert.ToString(sqlCommand.CommandText, CultureInfo.InvariantCulture)
                + "Failed. " + Convert.ToString(message, CultureInfo.InvariantCulture), innerException)
        {
            StringBuilder sb = new StringBuilder();
            foreach (SqlParameter param in sqlCommand.Parameters)
            {
                if (sb.Length > 0) sb.Append(",");
                sb.AppendFormat("{0}='{1}'", param.ParameterName, Convert.ToString(param.Value, CultureInfo.InvariantCulture));               
            }
            StringBuilder sbHeader = new StringBuilder();
            sbHeader.AppendLine(String.Format(CultureInfo.InvariantCulture,"{0} :{1} Failed. {2}", sqlCommand.CommandType, sqlCommand.CommandText, message));
            sbHeader.AppendFormat("Exec {0} ", sqlCommand.CommandText);
            sbHeader.Append(sb.ToString());
        }