3

我有一个控件,可以在回发时将表单结果保存回数据库。它通过遍历查询字符串来填充要保存的值。所以,对于下面的 SQL 语句(为了讨论而大大简化)......

UPDATE MyTable
SET MyVal1 = @val1,
    MyVal2 = @val2
WHERE @id = @id

...它会因此循环遍历查询字符串键:

For Each Key As String In Request.QueryString.Keys
    Command.Parameters.AddWithValue("@" & Key, Request.QueryString(Key))
Next

但是,我现在遇到的情况是,在某些情况下,其中一些变量可能不存在于查询字符串中。如果我没有在查询字符串中传递 val2,我会收到一个错误:System.Data.SqlClient.SqlException: Must declare the scalar value "@val2".

尝试检测 SQL 语句中的缺失值...

IF @val2 IS NOT NULL
UPDATE MyTable
SET MyVal1 = @val1,
    MyVal2 = @val2
WHERE @id = @id

... 失败了。

攻击这个的最好方法是什么?我必须用 RegEx 解析 SQL 块,扫描查询字符串中不存在的变量名吗?或者,有没有更优雅的方法?

更新:在 VB 代码隐藏中检测空值违背了将代码与其上下文分离的目的。我宁愿不要在我的函数中乱扔可能通过或未通过的每个可能的变量的条件。

4

4 回答 4

9

首先,我建议不要将查询字符串上的所有条目添加为参数名称,我不确定这是否不安全,但我不会冒险。

问题是你打电话

Command.Parameters.AddWithValue("@val2", null)

而不是这个,你应该打电话:

If MyValue Is Nothing Then
    Command.Parameters.AddWithValue("@val2", DBNull.Value)
Else
    Command.Parameters.AddWithValue("@val2", MyValue)
End If
于 2008-09-15T18:50:14.027 回答
0

更新:我给出的解决方案是基于它是一个存储过程的假设。 将默认值 Null 赋予 SQL 存储过程参数是否有效?

如果是动态 sql,始终传递正确数量的参数,无论是 null 还是实际值或指定默认值。

于 2008-09-15T18:51:16.660 回答
0

我喜欢使用这种AddWithValue方法。

我总是为“可选”参数指定默认 SQL 参数。这样,如果它为空,ADO.NET 将不包含该参数,存储过程将使用它的默认值。

我不必以这种方式处理检查/传递 DBNull.Value 。

于 2008-09-15T18:57:06.333 回答
0

在努力寻找一个更简单的解决方案之后,我放弃了并编写了一个例程来解析我的 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

这有点像 hack,但它允许我让我的代码幸福地忽略我的 SQL 查询的上下文。

于 2008-09-15T20:37:23.067 回答