Workflows innerhalb der Integration Services habe ich bisher primär über “Constraints” und bei komplexeren Abläufen zusammen mit speziellen Einschränkungen abgebildet. In einem aktuellen Projekt bin ich darüber gestolpert, wie Workflows fast ausschließlich über das aktivieren und deaktivieren – also der Eigenschaft “Disable” – eines Tasks erstellt wurden.
Da diese unterschiedliche Herangehensweise zu einer doch recht kontroversen Diskussion geführt hat, habe ich im Folgenden einmal ein Szenario mit beiden Vorgehensweisen nachgebaut, um die Unterschiede genauer zu erklären.
Das Demo-Paket hat 3 verschiedene Abläufe:
-
Task 2 so wie der Rest des Paketes werden nicht ausgeführt
-
Task 3 wird nicht ausgeführt, Task4 und Task5 sollen dennoch ausgeführt werden
-
Task A und Task B sollen nicht ausgeführt werden.
Das Paket wird dafür mit verschiedenen Variablen versehen, über die die einzelnen Abläufe gesteuert werden.
Der wichtigste Unterschied zwischen den beiden Varianten gleich vorweg:
Tasks die deaktiviert werden unterbrechen nicht den Ablauf eines Paketes sondern werden übersprungen bzw. ausgelassen.
Disable
Im ersten Schritt ist die Variante “Disable” zu sehen. Hier werden die Tasks und Sequenzcontainer über die jeweilige Expression “Disable” aktiviert bzw. deaktiviert.
Durch den installierten BIDS Helper sieht man in dem Paket über die magentafarbenen Ecken sehr gut wo Expressions gesetzt worden sind und dadurch das Paket beeinflusst wird.
Ablauf 1: Der gesamte relevante Teil des Paketes wird in einen Sequenzcontainer ausgelagert. Wenn der Task 2 – und somit das gesamte weitere Paket – nicht ausgeführt werden soll, wird der Sequenzcontainer “Sequenz A” über die Expression auf “Disable” gesetzt.
Ablauf 2: Task3 wird über die Expression auf “Disable” gesetzt. Da der Task nur “übersprungen” wird, werden Task4 und Task5 weiterhin ausgeführt.
Ablauf 3: Wie bei Ablauf 1, wird der gesamte Ablauf wieder in einen Sequenzcontainer ausgelagert und dieser durch die Expression auf “Disable” gesetzt. An dieser Stelle existiert kein Unterschied in der Handhabung zu Ablauf 1.
Constraints
Um diese Abläufe über “Constraints” und Ausdrücke zu realisieren, wird ein anderes Konzept verwendet. Die “Constraints” in dem Paket werden an verschiedenen Stellen mit Ausdrücken erweitert, zu sehen an dem jeweiligen Funktionszeichen .
Ablauf 1: Innerhalb des “Constraint” wird ein Ausdruck ausgewertet. Ist dieser True, so wird der nächste Task ausgeführt.
Ablauf 2: Ist die entsprechende Variable True, so wird Task3 ausgeführt, ist die Variable False, so wird Task4 ausgeführt. Zusätzlich muss für die verweisenden “Constraints” auf Task4 die Option “Logischer OR-Operator. Eine Einschränkung muss zu ‘True’ ausgewertet werden.” aktiviert sein. Dies wird in diesem Fall durch die gestrichelten Linien der Constraints angezeigt. Somit wird sichergestellt, dass entweder Task3 ausgeführt wurde oder der Ausdruck innerhalb des “Constraints” von Task2 auf Task4 gültig ist.
Ablauf 3: Wieder wird ein Ausdruck innerhalb des “Constraints” ausgewertet. Die Einschränkung von TaskA auf TaskB gibt an, das TaskB bei Erfolg ausgeführt werden muss, wodurch TaskB nicht ausgeführt wird, wenn Task nicht ausgeführt wird.
Und wo ist der Unterschied?
Grundsätzlich können mit beiden Optionen die jeweiligen Ziele erreicht werden, wenn man den Unterschied der beiden Varianten beachtet.
Ein deaktivierter Task wird übersprungen, ein nicht erfüllter Constraint beendet den entsprechenden “Zweig”.
Möchte man also einen Task überspringen, so kann man diesen deaktivieren oder man muss eine zusätzliche Umleitung um diesen Task erstellen.
Auch wenn die Unterschiede nicht wirklich sehr groß zu sein scheinen, ist es aus meiner Sicht nicht empfehlenswert, Workflows über das deaktivieren von Task zu erstellen – auch wenn es hier mit Sicherheit Ausnahmen geben mag.
Grundsätzlich finde ich Abläufe, die über die Constraints erstellt werden wesentlich logischer, da man sehr schnell sieht, wo Besonderheiten sind und dadurch den Ablauf besser versteht. Die Anzahl an Sequenzcontainer die für das de-/aktivieren verwendet werden, macht ein Paket wesentlich komplexer. Hinzu kommt noch, das es ohne den installierten BIDS Helper nicht ersichtlich ist, wann und wo Tasks deaktiviert werden.
Tasks die beim Start eines Paketes bereits deaktiviert sind, werden im BIDS bei der Ausführung weiterhin deaktiviert angezeigt. Dies kann während des Debuggens erheblich zu Verwirrungen führen.
Die Paketprotokollierung greift nicht vollständig, wenn Tasks beim Start eines Paketes deaktiviert sind.
Als rein subjektive Beobachtung – ich hab hier keine wirklichen Test gemacht – finde ich, das komplexere Pakete mit vielen Sequenzcontainer beim Laden erheblich länger für die Validierung brauchen als äquivalente Pakete, bei denen der Workflow über Constraints erstellt worden sind.
Über Feedback würde ich mich freuen, besonders wenn mir jemand einen Situation nennen kann, in der es Vorteilhafter ist, Tasks zu deaktivieren anstatt den Workflow entsprechend anzupassen.