Gestione di valori vuoti con ADO.NET e AddWithValue()
Domanda
Ho un controllo che, al postback, salva i risultati del modulo nel database.Popola i valori da salvare eseguendo l'iterazione della querystring.Quindi, per la seguente istruzione SQL (molto semplificata per motivi di discussione)...
UPDATE MyTable
SET MyVal1 = @val1,
MyVal2 = @val2
WHERE @id = @id
... scorrerebbe le chiavi della stringa di query in questo modo:
For Each Key As String In Request.QueryString.Keys
Command.Parameters.AddWithValue("@" & Key, Request.QueryString(Key))
Next
TUTTAVIA, ora mi trovo in una situazione in cui, in determinate circostanze, alcune di queste variabili potrebbero non essere presenti nella querystring.Se non passo val2 nella querystring, ottengo un errore: System.Data.SqlClient.SqlException: Must declare the scalar value "@val2"
.
Tenta di rilevare il valore mancante nell'istruzione SQL...
IF @val2 IS NOT NULL
UPDATE MyTable
SET MyVal1 = @val1,
MyVal2 = @val2
WHERE @id = @id
...Ha fallito.
Qual è il modo migliore per attaccare questo?Devo analizzare il blocco SQL con RegEx, cercando nomi di variabili non presenti nella querystring?Oppure esiste un modo più elegante per avvicinarsi?
AGGIORNAMENTO:Il rilevamento di valori null nel codebehind VB vanifica lo scopo di disaccoppiare il codice dal suo contesto.Preferirei non inquinare la mia funzione con condizioni per ogni variabile immaginabile che potrebbe essere passata o non passata.
Soluzione 3
Dopo aver faticato a trovare una soluzione più semplice, ho rinunciato e ho scritto una routine per analizzare la mia query SQL per i nomi delle variabili:
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
È un po' un trucchetto, ma mi permette di mantenere il mio codice completamente ignaro del contesto della mia query SQL.
Altri suggerimenti
Prima di tutto, suggerirei di non aggiungere tutte le voci sulla querystring come nomi di parametri, non sono sicuro che non sia sicuro, ma non correrei questo rischio.
Il problema è che stai chiamando
Command.Parameters.AddWithValue("@val2", null)
Invece di questo dovresti chiamare:
If MyValue Is Nothing Then
Command.Parameters.AddWithValue("@val2", DBNull.Value)
Else
Command.Parameters.AddWithValue("@val2", MyValue)
End If
Aggiornamento:La soluzione che ho fornito si basa sul presupposto che si tratti di un proc memorizzato.Fornire un valore predefinito Null ai parametri proc SQL Stored funzionerà?
Se si tratta di SQL dinamico, passare sempre il numero corretto di parametri, sia che si tratti di null o del valore effettivo, oppure specificare i valori predefiniti.
Mi piace usare il AddWithValue
metodo.
Specifico sempre i parametri SQL predefiniti per i parametri "facoltativi".In questo modo, se è vuoto, ADO.NET non includerà il parametro e la procedura memorizzata utilizzerà il suo valore predefinito.
Non devo occuparmi del controllo/passaggio di DBNull.Value in questo modo.