使用ADO.NET和AddWithValue()处理空值
时间:2020-03-05 18:54:13 来源:igfitidea点击:
我有一个控件,可以在回发时将表单结果保存回数据库。它通过遍历查询字符串来填充要保存的值。因此,对于以下SQL语句(为便于讨论,已大大简化)...
UPDATE MyTable SET MyVal1 = @val1, MyVal2 = @val2 WHERE @id = @id
...因此将循环遍历querystring键:
For Each Key As String In Request.QueryString.Keys Command.Parameters.AddWithValue("@" & Key, Request.QueryString(Key)) Next
但是,我现在遇到一种情况,在某些情况下,其中某些变量可能不存在于查询字符串中。如果我没有在查询字符串中传递val2,则会收到错误消息:`System.Data.SqlClient.SqlException:必须声明标量值" @ val2"。
尝试检测SQL语句中的缺失值...
IF @val2 IS NOT NULL UPDATE MyTable SET MyVal1 = @val1, MyVal2 = @val2 WHERE @id = @id
... 失败了。
最好的攻击方法是什么?我是否必须使用RegEx解析SQL块,扫描查询字符串中不存在的变量名?还是有一种更优雅的方法?
更新:在后面的VB代码中检测空值无法实现将代码与其上下文分离的目的。我宁愿不要为可能传递或者未传递的每个可能的变量提供条件。
解决方案
回答
首先,我建议不要在querystring上添加所有条目作为参数名称,我不确定这是不安全的,但我不会抓住这个机会。
问题是你在打电话
Command.Parameters.AddWithValue("@val2", null)
与此相反,我们应该致电:
If MyValue Is Nothing Then Command.Parameters.AddWithValue("@val2", DBNull.Value) Else Command.Parameters.AddWithValue("@val2", MyValue) End If
回答
更新:我给出的解决方案基于它是存储过程的假设。
将SQL Stored proc参数的默认值设置为Null是否可行?
如果它是动态sql,则始终传递正确数量的参数,无论它为null还是实际值或者指定默认值。
回答
我喜欢使用AddWithValue
方法。
我总是为"可选"参数指定默认的SQL参数。这样,如果它为空,则ADO.NET将不包含该参数,并且存储过程将使用其默认值。
我不必以这种方式处理检查/传递DBNull.Value的问题。
回答
在努力寻找一个更简单的解决方案之后,我放弃了并写了一个例程来解析我的SQL查询中的变量名:
Dim FieldRegEx As New Regex("@([A-Z_]+)", RegexOptions.IgnoreCase) Dim Fields As Match = FieldRegEx.Match(Query) Dim Processed As New ArrayList While Fields.Success Dim Key As String = Fields.Groups(1).Value Dim Val As Object = Request.QueryString(Key) If Val = "" Then Val = DBNull.Value If Not Processed.Contains(Key) Then Command.Parameters.AddWithValue("@" & Key, Val) Processed.Add(Key) End If Fields = Fields.NextMatch() End While
这有点骇人听闻,但它使我可以使自己的代码完全不了解SQL查询的上下文。