Come succede per l'impostazione dinamica dei connection manager oledb o snac (ho scritto qualcosa in quest'altro
post) è possibile anche lanciare più pacchetti esterni, configurando dinamicamente il connection manager di tipo file. Il task che ci consente di lanciare package residenti su SQL Server o su Filesystem è "Execute Package Task" (ho già accennato anche lui
qui..)
Quest'ultimo task ci consente di richiamare altri package esterni per effettuare operazioni al di fuori del SSIS da cui l'abbiamo lanciato, con la possibilità di eseguirlo anche in modalità
Out Of Process, ovvero al di fuori del processo che gestisce il SSIS chiamante.
L'interfaccia per configurarlo si divide in tre parti:
Sezione GeneralConsente di specificare il nome univoco del task e la sua descrizione.
Sezione PackageConsente di specificare la locazione in cui reperire il package, la connessione (in caso di filesystem) o una connessione a sql server abbinata al nome del package (nel caso di SQL Server), una eventuale password e il tipo di esecuzione, se nello stesso processo del chiamante o in un processo a parte.
Sezione ExpressionQuesta parte è identica alla sezione expression di ogni task di SSIS. Ovviamente con la possibilità di gestire proprietà differenti.
Per arrivare alla configurazione dinamica dei package esterni da eseguire, illustriamo un semplice esempio:
Supponiamo di avere l'esigenza di lanciare in serie tre pacchetti, package1.dtsx, package2.dtsx e package3.dtsx.
Ora, ammettiamo di avere l'elenco dei SSIS da lanciare all'interno di una tabella di configurazione. Ogni SSIS deve essere eseguito all'interno del processo del chiamante.
Procediamo passo passo..
Prima cosa da fare, aggiungere un connection manager di tipo FILE (Existing) chiamato
PackageN che punti ad un qualunque file (non ci interessa, tanto poi cambieremo dinamicamente il path). Esso ci servirà per dire cosa lanciare all'Execute Package Task.
La prima parte del SSIS principale si occupa di ricavare i dati ordinati da eseguire. Utilizzaimo uno script task per simulare una semplice tabella di configurazione, senza usufruire di database o xml. Lo script è il seguente:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Public Class ScriptMain
Public Sub Main()
' datatable
che conterrà l'elenco dei SSIS da chiamare
Dim DT As New DataTable("tempTable")
Dim DR As DataRow
' colonne di
definizione del datatable
DT.Columns.Add(New
DataColumn("SSISName", GetType(String)))
DT.Columns.Add(New DataColumn("SSISPath",
GetType(String)))
' aggiungo i record
' ----------------------------------------------------------
DR = DT.NewRow()
DR("SSISName") = "Package1.dtsx"
DR("SSISPath") = "D:\SSIS\Package1.dtsx"
DT.Rows.Add(DR)
DR =
DT.NewRow()
DR("SSISName") = "Package2.dtsx"
DR("SSISPath") = "D:\SSIS\Package2.dtsx"
DT.Rows.Add(DR)
DR =
DT.NewRow()
DR("SSISName") = "Package3.dtsx"
DR("SSISPath") = "D:\SSIS\Package3.dtsx"
DT.Rows.Add(DR)
'
----------------------------------------------------------
Dts.Variables("SSISList").Value = DT
Dts.TaskResult = Dts.Results.Success
End Sub
End Class
Abbiamo creato un semplice datatable con tre righe ognuna delle quali ha l'importante informazione del path in cui troveremo il SSIS da lanciare. Del nome, in realtà non ci interessa granchè, ai fini dell'esempio. Alla fine del listato assegnamo ad una variabile dichiarata come di Lettura Scrittura il valore del nostro datatable. La variabile SSISList è un oggetto così dichiarato:
Ora abbiamo il nostro oggetto popolato dallo script e pronto per essere ciclato. Aggiungiamo un for each container così definito:
In questo modo l'iteratore ADO cicla, riga per riga sulla nostra variabile oggetto SSISList. Ad ogni ciclo inoltre, valorizziamo la variabile del path, nella sezione
Variable Mappings:
Come possiamo vedere vi è anche una variabile di appoggio per il nome, ma interessiamoci solo di quella per il path,
SSISPath. A questo punto possiamo scegliere due strade. Utilizzare uno script che assegni il valore della variabile SSISPath al connection manager
PackageN oppure impostare il connection manager con le Expressions.. In questo esempio seguiremo la prima via, perchè ci permette di rendere più visibile la modifica del percorso del file. Le expression a volte sono piuttosto nascoste
.. Lascio a voi l'implementazione con il secondo metodo
.
Ecco quindi lo script di assegnazione del connection manager:
Notiamo due variabili di sola lettura,
ConnectionManagerName e
SSISPath. La prima contiene il nome del connection manager da cambiare (Nel nostro esempio
PackageN) e la seconda è la variabile mappata nel ciclo dei SSIS da lanciare. Il codice è il seguente:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Public Class ScriptMain
' proprietà che gestisce la variabile in sola lettura SSISPath
Private ReadOnly
Property SSISPath() As
String
Get
Return Dts.Variables("SSISPath").Value.ToString()
End Get
End Property
' proprietà che
gestisce la variabile in sola lettura ConnectionManagerName
Private ReadOnly
Property ConnectionManagerName() As String
Get
Return Dts.Variables("ConnectionManagerName").Value.ToString()
End Get
End Property
' proprietà che scrive il valore della connection string
del connection manager corrente
Private WriteOnly Property CurrentConnectionManagerConnectionString() As String
Set(ByVal value As String)
Dts.Connections(Me.ConnectionManagerName).ConnectionString = value
End Set
End Property
Public Sub Main()
Me.CurrentConnectionManagerConnectionString = Me.SSISPath
Dts.TaskResult = Dts.Results.Success
End Sub
End Class
Per comodità ho definito delle proprietà in modo da rendere più gestibile il contenuto dello script. Due proprietà ReadOnly per la lettura dei dati del connection manager ed una in sola scrittura per scrivere all'interno della connectionstring del connection manager il valore del path (come si nota nel metodo Main).
Il passo successivo (e finale) è quello di aggiungere l'execute package task, legandolo alla connessione file fittizia, che a runtime cambierà in base ai dati di ogni ciclo e configurandolo per eseguire i package via filesystem:
Il SSIS finale sarà il eguente:
N.B. Ovviamente i tre ssis da eseguire e che sono elencati nel primo script, devono esistere nella posizione di destinazione definita (D:\SSIS). Nel caso in cui anche solo uno dei file non esista o non sia in corretta posizione, verrà sollevata un'eccezione di file not found, tranquillamente gestibile, senza bloccare il flusso di lavoro.
CONCLUSIONI
Come si può facilmente notare da questo post, la possibilità di rendere dinamico il lancio di pacchetti esterni non è cosa complessa. Facciamo attenzione ovviamente a tutti i settings possibili di ogni task. Ad esempio l'Execute Package Task, consente anche di eseguire, come dicevamo, un SSIS out of process. Tutte le analisi per decidere se eseguire nello stesso processo o al di fuori devono essere fatte nella misura delle risorse che occuperemo, dei carichi della macchina, se si tenderà a parallelizzare le chiamate o a mantenerle sequenziali. E' importante capire come muoverci in ogni caso che ci si presenta di fronte. L'utilizzo di Execute Package Task inoltre, può essere comodo per la modularità, per il grouping, e per scindere un grosso pacchetto in altri più piccoli. Quest'ultimo metodo di sviluppo permette una migliore gestione dell'intero progetto e comunque riduce di molto le attese durante le fasi di validazione a design time
..
Stay tuned!