找出导致异常的查询

时间:2013-04-08 15:07:35

标签: c# sql oledbcommand

我的插件有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和类似的东西。虽然我的大多数记录都已正确插入,但我想知道哪些插入查询确实导致了错误。我怎么能弄明白呢?

N.B。在使用此方法之前,我可以访问我的查询字符串,并立即发现错误。现在我想我对SQL注入的免疫力会给自己造成一些混乱

4 个答案:

答案 0 :(得分:1)

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

您可以在初始“GETCLICKS”日志条目之后立即将每个参数值写入日志。这样可以让您更好地了解来自用户的错误格式。

答案 1 :(得分:1)

标准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 );

答案 2 :(得分:0)

参数Value属性是Object泛型类型。所以它接受你分配给它的任何东西。当然,这不是处理数据的好方法。我将尝试将值转换为参数的相应数据类型,并避免将伪值发送到数据库。这样,您将立即在参数分配中捕获错误,而不是在执行插入

例如:

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

如果这不是一个有效的日期时间,它将在Convert.ToDateTime失败,你会注意到你的日志

答案 3 :(得分:-1)

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

创建一个构造函数,它将oledbcomndand作为输入参数,您可以尝试通过循环参数集合来记录OldedbComamnd.CommandText。如下面的示例所示,SQLcommand(与OLedbCommand或多或少相同)

或Easy Way - 抛出异常时,在日志中写入OLDEBCommand.ComamndText。

下面是我为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());

        }