[VB.NET] Utilizzare SqlCommand per processare istruzioni T-SQL multiple (it-IT)
Introduzione
In questo breve articolo, vedremo un metodo poco conosciuto di utilizzare la classe SqlCommand, che viene normalmente impiegata per eseguire una singola operazione su una base dati. Il linguaggio di programmazione degli esempi a seguire sarà Visual Basic .NET, ma i concetti si applicano anche a C#.
Interrogare una tabella
Il modo più comune di usare un SqlCommand é di eseguire tramite esso una singola istruzione, sia per selezionare record che per effettuare le altre operazioni più note, siano esse update, insert, delete. Nel seguente scorcio di codice, viene mostrato un semplice metodo con cui aprire una connessione, e selezionare, da un'ipotetica tabella Products, quei records il cui campo Status sia uguale a zero. Tali record serviranno, mediante l'uso di un DataAdapter, per popolare un DataTable ad uso futuro.
Dim dt as DataTable
Using conn As New SqlConnection("<YOUR_CONNECTION_STRING>")
conn.Open()
Dim _sqlCommand As New SqlCommand("SELECT ProdId FROM Products WHERE Status = 0", conn)
Dim ta As New SqlDataAdapter(_sqlCommand)
ta.Fill(dt)
End Using
Istruzioni multiple
Ma cosa accade quando necessitiamo di eseguire istruzioni multiple? Quando una query diventa eccessivamente complessa, o richiede più di un singolo passaggio per essere eseguita, quali sono le opzioni in gioco per lo sviluppatore? Diverse situazioni possono essere gestite tramite una sola query ben scritta, ma ci sono occasioni in cui una query deve essere "spacchettata" in sotto-elementi, magari desiderando di mantenere più leggibile l'intero script, oppure per evitare sovraccarichi prestazionali sul nostro motore di database, causato da query di dimensioni notevoli o non scritte in modo efficiente.
Un primo approccio, più dispendioso, consiste nel creare tanti SqlCommands quanti ne servono. Ipotizziamo di dover generare una tabella temporanea, per riempirla di quei record di Products aventi Status pari a zero, per poi aggiornare un secondo campo ad un dato valore, quindi eseguendo il join del nostro recordset con un'altra tabella, recuperando il recordset risultante cancellando però la tabella temporanea subito dopo.
Uno sviluppatore potrebbe essere tentato di impiegare un primo SqlCommand per la creazione della tabella temporanea, un secondo per l'insert dei record che soddisfano le condizioni imposte, un terzo per l'update, e così via. Anche se ciò può essere fatto (ed esistono situazioni che possono richiedere esplicitamente un approccio di questo tipo), il risultato potrebbe essere quello di ottenere un codice più complesso da manutenere, e più pesante.
Una soluzione concisa
Un uso non troppo noto di SqlCommand, risiede nella sua possibilità di eseguire interi scripts SQL. Ciò significa che uno script SQL che avremo sviluppato e testato, ad esempio su Management Studio, potrà essere passato ad un SqlCommand per una sua completa esecuzione. Consideriamo lo pseudo-codice a seguire:
Dim sqlCmd as String = "CREATE TABLE #mytemp (ProdId INT, ProdCode VARCHAR(25), MyColumn INT) " & Environment.NewLine & _
"INSERT INTO #mytemp (ProdId, ProdCode) SELECT ProdId, ProdCode FROM Products " & Environment.NewLine & _
"UPDATE #mytemp SET MyColumn = 2 " & Environment.NewLine & _
"SELECT * FROM #mytemp " & Environment.NewLine & _
"DROP TABLE #mytemp "
Dim dt as DataTable
Using conn As New SqlConnection("<YOUR_CONNECTION_STRING>")
conn.Open()
Dim _sqlCommand As New SqlCommand(sqlCmd, conn)
Dim ta As New SqlDataAdapter(_sqlCommand)
ta.Fill(dt)
End Using
Come si può notare, non abbiamo utilizzato SqlCommand come esecutore di una singola istruzione ma, piuttosto, gli abbiamo passato un piccolo script, che svolgerà diverse operazioni. Quando eseguiremo il comando, per riempire la DataTable, l'intero instruction set verrà eseguito. La DataTable sarà popolata dei campi e dei valori relativi all'ultima select incontrata, ma anche le restanti istruzioni saranno lanciato. Quindi, nell'eseguire il nostro codice, una singola istanza di SqlCommand si troverà a gestire la creazione della tabella temporanea, e le successive istruzioni di insert/update/select/drop.
Conclusione
Un approccio di questo tipo può essere molto utile per avere un codice VB/C# più leggero, ma - soprattutto - quanto visto fin qui è una chiara dimostrazione delle potenzialità del namespace System.Data.SqlClient, che lo rende una delle scelte più adatte ed intelligenti per quanto concerne la comunicazione con basi dati e loro gestione.
Altre lingue
Il presente articolo è disponibile nelle seguenti lingue: