找出哪个查询导致了异常
本文关键字:异常 查询 | 更新日期: 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());
}