Category: "Integration Services"

Integration Services: Looping & “continue on error”

Eine häufige Aufgabe bei der Arbeit mit Integration Services Paketen ist es, eine Routine in einer Schleife auszuführen.

Nehmen wir den konkreten Fall: ein For Each-Loop zum rekursiven Auslesen von Textdateien aus einer Verzeichnisstruktur und Verschieben an einen Zielort.

Wenn die Operation aufgrund von einer geöffneten Datei (z.B. der Log-Writer Prozess) fehlschlägt, schlägt damit der Task “Move file” fehl. Sodann der Container “For Each Loop”, und dann das gesamte Paket. Das ist das Standardverhalten: das Event “Error” wird propagiert.

Das sieht in etwa so aus (hier mit einen For Loop):

SSIS_EventPropagation_standard

Man sieht trotz der versuchten “Fehlerbehandlung” in dem Script-Task “SCR-Fail” schlägt der Container fehl.

Das ist in diesem Fall aber nicht unbedingt das gewünschte Ergebnis.
Man möchte, das die Operation einfach mit der nächsten Datei fortfährt und eventuell liegengebliebene Dateien in einem späteren Durchlauf einfach holen.

Dafür muss man das propagieren des Fehlers auf Container-Ebene unterbinden. Die dafür extra vorhandene Systemvariable “Propagate” ist ausnahmsweise deswegen auch manuell änderbar. Allerdings gibt es diese nur in den Event Handlern.

Das heisst für den fehlschlagenen SQL-Task in diesem Beispiel ist ein EventHandler für “OnError” anzulegen. Dort findet man dann die besagte Variable und schaltet sie auf False

SSIS_EventPropagation_SystemVariablePropagate 

 

Das würde an sich schon genügen, um das Paket einfach weiterlaufen zu lassen.

Allerdings ist es in der Regel wünschenswert, im Anschluss eine bedingte Reaktion auf das erfolgreiche oder erfolglose Verschieben der Datei erfolgen zu lassen. In diesem Beispiel ein T-SQL-Schritt bei Erfolg, und der Script-Task “Fail” bei Misserfolg.

Da nun kein Fehler mehr propagiert wird, ist ein kleiner Kunstgriff vonnöten: Man definiert sich eine Variable, welche im Fehlerfall einen anderen Wert erhält und liest diese dann bei dem Precedence-Constraint zusätzlich mit aus.

Am einfachsten geht das mit dem im Fehlerfall ohnehin vorhandenen ErrorCode – innerhalb des EventHandler natürlich.

Dort leitet man den Wert der Systemvariable “ErrorCode” einfach in seine eigens zuvor angelegte User-Variable um:

Dts.Variables("User::ErrorCode").Value = Dts.Variables("System::ErrorCode").Value

Im ControlFlow wird dann ein “OnCompletion” – Precedence Constraint verwendet, und zusätzlich die Variable in der Expression "@[User::ErrorCode] != 0" ausgewertet

Das gewünschte Ergebnis verhält sich dann so:

SSIS_EventPropagation_Result

Der Fehler im Task wird abgehandelt, und die Arbeit wird fortgesetzt.

 

happy coding :)

 

Andreas Wolter

 

Sarpedon Quality Lab