2013-04-08 49 views
0

我有一个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注入的免疫力造成了一些困惑

+0

在你的'catch'只是注销参数,就像你以前注销你的SQL字符串一样。 – 2013-04-08 15:10:40

+0

注意,如果'args [4]'可能受到用户的影响,则此代码仍然容易受到SQL注入的影响。 – tomfanning 2013-04-08 15:20:01

+0

您可能会发现使用'OleDbParameterCollection.AddWithValue()'可以更轻松地进行操作,而不需要您指定参数类型或长度。 http://msdn.microsoft。com/en-us/library/system.data.oledb.oledbparametercollection.addwithvalue(v = vs.100).aspx – tomfanning 2013-04-08 15:21:43

回答

1

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

您可以在初始'GETCLICKS'日志条目之后立即将每个参数值写入日志。这会给你一个更好的想法,即来自用户的价值是不正确的格式。

0

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

时。例如:

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

如果这不是一个有效的datetime它将在Convert.ToDateTime和你失败会注意到在您的日志中

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

     } 
+0

CommandText将不包含参数值。 – tomfanning 2013-04-08 15:23:07

+0

@tomfanning:好的,对不起,纠正了文字。引发自定义异常因此,在这种情况下,循环遍历参数集合并记录值。我想这应该工作。 – dekdev 2013-04-08 15:26:44

相关问题