Seguendo il consiglio di Maria, un’amica che ha lasciato un commento sul post
Variabili e SSIS Configurations, ho deciso di scrivere questo post totalmente incentrato sulla gestione delle variabili negli script.
Le variabili (di cui ho già scritto una overview
qui)in SSIS sono gestite in maniera totalmente differente rispetto a come lo erano per DTS. Per chi non lo sapesse, prima una variabile era definita GLOBALE (infatti si chiamava
GlobalVariable) e quindi ogni task poteva accedere tranquillamente ad essa, in ogni momento. Inoltre erano fortemente modificabili, ovvero, cambiandone il valore a runtime, rimanevano impostate così come l’esecuzione le valorizzava. Questo creava problemi soprattutto in fase di distribuzione dei pacchetti, visto che i valori di ogni variabile erano del tutto riferiti all’ultima esecuzione e che le variabili stesse, in molti casi, erano legate a proprietà di oggetti del package.
In SSIS tutto questo cambia.
Viene innanzitutto introdotto il concetto di
SCOPE, ovvero di visibilità, di ambito.
Una variabile può essere di visibilità di un task/container piuttosto che di un altro e così risulta sia visibile a tutti i figli dell’oggetto in cui è dichiarata che invisibile agli oggetti in cui l’oggetto stesso è contenuto.
Ad esempio, prendiamo questa semplice porzione di pacchetto, un contenitore di sequenza ed uno script interno al container:
Clickando sull’oggetto
Contenitore, si possono aggiungere le variabili di
SCOPE Contenitore.
Clickando su
Task figlio, variabili di
SCOPE Task figlio.
Di conseguenza,
Task figlio accederà alle variabili dichiarate sia in
Contenitore, sia in se stesso, mentre
Contenitore avrà la possibilità di vedere solo le variabili dichiarate in se stesso.
Lo Scope è visibile nella finestra delle variabili, accessibile clickando il destro del mouse sullo stage del control flow e selezionando “Variabili” (Variables).
In SSIS le variabili mantengono il valore che gli si assegna a design-time. Quindi, a runtime, se indicato nel package, cambiano valore, ma alla fine dell’esecuzione dell’applicazione, tornano ai valori stabiliti in principio.
Le variabili sono inoltre tipizzabili secondo i tipi di dato definiti nel .NET Framework.
Possono essere utilizzate come mapping di dati provenienti da resultset, possono essere configurate dagli strumenti di Configurazione di SSIS, possono essere utilizzate via script e nelle trasformazioni di dati.
Fare un esempio per ogni casistica prenderebbe troppo spazio, per cui vedremo solo come gestirle tramite lo
Script task.
Immaginiamo di voler leggere la variabile
Valore1 e la variabile
Valore2, entrambe ti tipo Int32, e di sommarle direttamente nello script definito nel
Task Figlio. Il valore tornato dalla somma lo passeremo in una variabile String, che chiamiamo
Risultato, di scope globale, ovvero visibile a tutto il pacchetto.
Come prima cosa si aggiunge la variabile
Risultato nell’apposita finestra tramite il pulsante cerchiato di rosso in figura, clickando prima sullo stage del pacchetto (ovvero sul control flow, dove non ci sono altri oggetti):
Si rinomina correttamente il valore fornito di default nel nome della variabile e si cambia il tipo, selezionando String. Una volta fatto ciò, si passa all’impostazione delle proprietà dello script, ovvero del task che effettuerà la somma,
Task figlio.
La sezione da impostare è quella denominata
Script. Per passare le variabili da utilizzare allo script è sufficiente indicarne un elenco, in cui ognuna è separata dall’altra tramite una virgola.
N.B. Se passiamo variabili che hanno ambito non idoneo con questo script, ad esempio una variabile di un task esterno al contenitore in cui risiede
Task figlio, non avremo, a runtime, nessuna eccezione, poiché non viene effettuato nessun controllo. L’eccezione l’avremo però, se all’interno dello script proveremo ad utilizzare quella particolare variabile. Comunque sia è buona norma fare attenzione a passare quelle corrette.
Da notare che le proprietà interessate sono fondamentalmente due,
ReadOnlyVariables,
ReadWriteVariables. Le prime sono le variabili di
sola lettura mentre le altre sono di lettura/scrittura. Quindi le prime possono essere solo consultate, mentre le altre possono anche essere modificate.
Premendo il pulsante
Progetta Script.. (Design Script) nella medesima sezione, apparirà l’editor su cui scriveremo codice per effettuare la somma.
Per accedere alle variabili è necessario usare l’oggetto Dts, collezione Variables. Come ogni collezione, possiamo accedere sia tramite indice numerico (un numero che definisce la posizione nella collection) che tramite una stringa, che, in questo caso, definisce il nome della variabile a cui accedere.
N.B. Il nome da passare alla collezione è CASE SENSITIVE. Nel nostro caso, scrivendo
valore1 invece di
Valore1, avremo un’eccezione. SSIS non troverà variabili con quel nome.
Ma ecco l'esempio:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Public Class ScriptMain
Public Sub Main()
' Ricavo il valore delle due variabili Valore1 e Valore2, tramite la collection
' Variables, dell'oggetto Dts.
' Inoltre converto il valore in Int32, ovvero lo stesso indicato nelle var sul
' package.
Dim myValore1 As Int32 = CType(Dts.Variables("Valore1").Value, Int32)
Dim myValore2 As Int32 = CType(Dts.Variables("Valore2").Value, Int32)
' Imposto nella variabile Risultato il risultato della somma, utilizzando sempre
' l'oggetto Dts.
' Siccome Risultato è stringa, devo convertire la somma in stringa, tramite ToString()
Dts.Variables("Risultato").Value = "Risultato: " & (myValore1 + myValore2).ToString()
' Visualizzo il risultato
MsgBox(Dts.Variables("Risultato").Value.ToString())
Dts.TaskResult = Dts.Results.Success
End Sub
End Class
Eseguendo il package, premendo il tasto destro del mouse sul file nella soluzione, avremo il seguente risultato:
Quello nello script poteva essere direttamente scritto nel seguente modo, senza passare per forza tramite due variabili di appoggio:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Public Class ScriptMain
Public Sub Main()
' Imposto nella variabile Risultato il risultato della somma, utilizzando sempre
' l'oggetto Dts.
' Siccome Risultato è stringa, devo convertire la somma in stringa, tramite ToString()
Dts.Variables("Risultato").Value = "Risultato: " & _
(CType(Dts.Variables("Valore1").Value, Int32) + _
CType(Dts.Variables("Valore2").Value, Int32)).ToString()
' Visualizzo il risultato
MsgBox(Dts.Variables("Risultato").Value.ToString())
Dts.TaskResult = Dts.Results.Success
End Sub
End Class
Il tutto eseguito su una riga sola. Ho utilizzato variabili di appoggio per rendere più chiara la lettura del codice.
Tramite script task (vale anche nello script transformation nel data flow) quindi, dobbiamo sempre indicare le varaibili di lettura e quelle di lettura/scrittura che utilizzeremo, e perciò quelle da non modificare e quelle da modificare.
Credo che lo script task sia l’unico che necessiti di una effettiva puntualizzazione per ciò che riguarda la gestione delle variabili. Come ripeto, possiamo però trovarle anche nelle Expressions, nel mapping di colonne di un resultset, nelle condizioni di worflow, e così via.