Обработка пустых значений с помощью ADO.NET и AddWithValue()

StackOverflow https://stackoverflow.com/questions/65566

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня есть элемент управления, который при обратной передаче сохраняет результаты формы обратно в базу данных.Он заполняет значения, которые необходимо сохранить, путем итерации по строке запроса.Итак, для следующего оператора 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

...провалился.

Какой лучший способ атаковать это?Должен ли я анализировать блок SQL с помощью RegEx, сканируя имена переменных, отсутствующие в строке запроса?Или есть более элегантный способ подойти?

ОБНОВЛЯТЬ:Обнаружение нулевых значений в коде VB противоречит цели отделения кода от его контекста.Я бы предпочел не засорять свою функцию условиями для каждой мыслимой переменной, которая может быть передана или не передана.

Это было полезно?

Решение 3

Пытаясь найти более простое решение, я сдался и написал процедуру для анализа моего 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-запроса.

Другие советы

Прежде всего, я бы посоветовал не добавлять все записи в строку запроса в качестве имен параметров. Я не уверен, что это небезопасно, но я бы не стал рисковать.

Проблема в том, что ты звонишь

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

Вместо этого вы должны позвонить:

If MyValue Is Nothing Then
    Command.Parameters.AddWithValue("@val2", DBNull.Value)
Else
    Command.Parameters.AddWithValue("@val2", MyValue)
End If

Обновлять:Решение, которое я дал, основано на предположении, что это хранимая процедура.Будет ли работать установка значения по умолчанию Null для параметров процедуры, хранящихся в SQL?

Если это динамический SQL, всегда передавайте правильное количество параметров, будь то нулевое значение или фактическое значение, или указывайте значения по умолчанию.

мне нравится использовать AddWithValue метод.

Я всегда указываю параметры SQL по умолчанию для «необязательных» параметров.Таким образом, если он пуст, ADO.NET не будет включать этот параметр, а хранимая процедура будет использовать его значение по умолчанию.

Таким образом мне не приходится иметь дело с проверкой/передачей DBNull.Value.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top