Category: "Integration Services"
Dieser Blog ist umgezogen // This Blog has moved: http://andreas-wolter.com/blog/
Sep 20th
http://andreas-wolter.com/blog/
Liebe Leser |
Dear Readers |
Die aufwändige Mehrsprachigkeit (Deutsch und Englisch professionell manuell übersetzt) wird beibehalten – aber Layout-technisch anders gelöst. Damit dürfte ich immer noch den einzigen mehrsprachigen IT-Blog weltweit betreiben. |
The complex multilingualism (German and English professionally manually translated) is being continued – but solved differently in terms of layout. With that I most likely still operate the only multilingual IT-Blog worldwide. |
Mein aktueller Artikel, der erstmalig ausschließlich auf der neuen Website zu finden ist, lautet: Optimieren von Workflows mit In-Memory und nativ kompilierten Objekten - oder wie es nicht funktioniert |
My currently last article, which is exclusively available at the new website for the first time, is Optimizing workflows with In-Memory and Natively Compiled Objects - or how it does not work |
Cu at my new Blog
Andreas
Integration Services: Looping & “continue on error”
Mär 18th
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):
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
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:
Der Fehler im Task wird abgehandelt, und die Arbeit wird fortgesetzt.
happy coding :)
Andreas Wolter