In einem vorangegangenen Eintrag hatte ich die Idee der Quarantäne vorgestellt, für die wir ein VB-Programm geschrieben haben, das in einem SSIS-Paket das Fehlerhandling umstellt.
DLLs einbinden
Als erstes müssen wir die folgenden DLLs einbinden:
also:
- Microsoft.SqlServer.DTSPipelineWrap
- Microsoft.SqlServer.DTSRuntimeWrap
- Microsoft.SqlServer.ManagedDTS
Diese müssen dann mit Imports (VB) bzw. using (c#) eingebunden werden – hier immer die VB-Beispiele:
Imports System
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports System.Runtime.InteropServices
Paket laden
Als erstes wollen wir das SSIS-Paket laden und wieder speichern:
Dim ssisApp As New Microsoft.SqlServer.Dts.Runtime.Application
Dim pName As String = “C:\meineProjekte\Paket.dtsx”
Dim package As New Package
package = ssisApp.LoadPackage(pName, Nothing)
ssisApp.SaveToXml(“neuerName.dtsx”, package, Nothing)
Alle Tasks ermitteln
Nun wollen wir in dem SSIS-Paket alle Tasks durchlaufen, um sie verändern zu können. Dazu enthält das SSIS-Paket eine Property “executables”, diese enthält alle Tasks der ersten Ebene.
Mit einer Schleife können wir diese durchlaufen:
For Each e As Executable In package.executables
Next
Allerdings erreichen wir dabei nur die Tasks der ersten Ebene.
In SSIS gibt es aber Tasks, die selber wieder Tasks beinhalten:
- Sequence
- For Each Loop
- For Loop
Diese interne Struktur kann man einfach in der SSIS-Umgebung anhand des Package Explorers sehen. In meinem Beispiel habe ich eine Sequence mit 2 Data Flows und nach der Sequence noch einen Data Flow (namens “skript”):
Um alle Tasks durchlaufen zu können, müssen wir also rekursiv vorgehen:
im Hauptprogramm:
…
processAllExecutables(package.Executables, 1)
…
und dann als eigene Methode:
Private Sub processAllExecutables(
ByVal executables As Executables,
ByVal depth As Integer)
For Each e As Executable In executables
…
Dim d1 As Integer = depth + 1
If TypeOf e Is ForLoop Then
processAllExecutables(CType(e, ForLoop).Executables, d1)
End If
If TypeOf e Is Sequence Then
processAllExecutables(CType(e, Sequence).Executables, d1)
End If
If TypeOf e Is ForEachLoop Then
processAllExecutables(CType(e, ForEachLoop).Executables, d1)
End If
Next
End Sub
Wie man sieht, kann man über TypeOf … Is <<Typ>> abfragen, ob die Task e einen bestimmten Typ hat. Bei den oben genannten Typen rufen wir dann die selbe Methode rekursiv auf – ich habe der Übersichtlichkeit halber die Tiefe als zusätzlichen Parameter übergeben, auch wenn das nicht unbedingt notwendig ist.
Somit haben wir das Ziel des heutigen Blogs fast erreicht: Wir durchlaufen alle Tasks. Als nächstes müssen wir Data Flows erkennen und verarbeiten.
DataFlows werden in der SSIS-API als TaskHost bezeichnet. Deswegen können wir das so abprüfen:
If TypeOf e Is TaskHost Then
…
End If
Damit haben wir eine Schleife über alle Data Flows programmiert.