0

I have an OleDbCommand for my inserts that I have tried to implement to avoid SQL injection. Before that I used simple strings for my queries and I didn't like that. Now my piece of code for inserting records looks like this:

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

I have thousands of inserts and I see from my log that some of them are not correctly inserted. The exception tells me e.g. cannot convert from bigint to datetime and stuff like that. Although most of my records are inserted correctly, I want to know which of these insert queries exactly caused the error. How can I figure that out?

N.B. Before using this method I had access to my query string and I found the error instantly. Now I guess my immunity to SQL injection is causing some confusion for myself

4

4 回答 4

1

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

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

于 2013-04-08T15:12:05.400 回答
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 );
于 2013-04-08T15:16:55.283 回答
0

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

例如:

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

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

于 2013-04-08T15:16:14.107 回答
-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());

        }
于 2013-04-08T15:16:56.170 回答