Author Archive

SSIS Pattern: Naming Convention Part I

Daniel Esser

A naming convention is a convention for naming things. The intent is to allow useful information to be deduced from the names based on regularities. For instance, in Manhattan, streets are named in two different fashions. East-West streets are called “Streets” and North-South streets called “Avenues”.

First we have to identify which entities have to be named in SSIS:

  • Projects
  • Packages (filename and identification name)
  • Configurations
  • Loggers
  • Connections
  • Variables
  • Control Flow and Data Flow items

Secondly it is not important which naming convention you use. It is important that you use a naming convention. There is a good article about naming conventions on Wikipedia you could use for inspiration. The CamelCase naming convention is often used in programming, so I decided to use it for the following examples.

Thirdly we need a clear and intuitive naming definition on how to describe the listed entities above. A naming definition of an entity assumes that we know how to describe important properties of the entity. So what are the important properties of the listed entities?

The Project Name

The name of the SSIS-Project gives a developer an hint which technical task or problem is solved inside. This name is the key entry point to a technical solution, a name for a jigsaw piece. Is is not best practise to bunch all technical things together. Sketch out the system boundaries and name them. Imagine it is a piece of a jigsaw. What picture (the name) have to be on the piece so you can assign it to the right place in the whole.

The Package Name

The package name is related to the given project name. A package is a small piece of the entire project. Without it the entire project can’t exist.

A package can do many things. It could be a control package, which starts other packages. It could be a package which start dimension or cube processing or it loads data from external or operative data sources into a local database for further processing. We can see that there are at least three different things a package can do: Control, Load and execute functional things like sending emails or starting dimension processing. So it suggests itself to use this information for the package naming definition. For example you could use the following prefixes in the package name:

  • Ctrl for packages which controls the execution of other packages
  • Load for packages which loads data
  • Func for packages which do some functional things like sending mails etc. pp.

Based on this we can go further. For Ctrl and Func packages it is obvious how to name them further. The simple questions are: What is the package to be controlled? What functional thing the package will do? Some examples:

  • CtrlMaster - A master control package for the whole project
  • CtrlCubeProcessing - A package which calls other packages to process dimensions and cubes in a non default manner
  • FuncSendSuccMail - Send a success mail to some people after processing cubes
  • FuncValidateMailAdresses - A package which validates a table with mail addresses. It marks which are correct and which not.

A load package is somewhat specific. Mostly there is at least one source and one target. So load packages can operate on different databases, tables, schemas etc. pp. The package name should reflect that fact. Here at ORAYLIS we have a process model on how to load data for Datawarehousing. We arrange the whole loading process into three layers: Extraction-Layer, Working-Layer and Frontroom. The Extraction-Layer hold the raw data from external and operative data sources. You could think of it as a one-to-one copy in a relational database or the interface to the outside world. In the Working-Layer we put data together (joining tables, calculating new columns, renaming, data cleansing etc.). The Frontroom-Layer is the actual Datawarehouse. So we have three important layers for loading a Datawarehouse. This could lead us to the following naming definition for Load-Packages.

  • LoadExtract - A package which loads data from an operative or external data source
  • LoadWork - A package which modifies the loaded data from the Extraction-Layer
  • LoadFront - A package which fills the Datawarehouse with data from the Work or Extraction-Layer

It is possible to have more than one Extraction-, Work- or Frontroom-Layer. Simply add the name of the layer (or other important information) at the end of the package name. For example LoadFrontSalesDimCustomer if the package fills the Customer Dimension for the Sales Datawarehouse which is stored in the Frontroom-Layer. The final naming definition for Load-Packages could be

“Load” {Logical Layer} {Database Name or abbreviation} {Tablename/Dimension/Fact}

Connections

Based on the naming conventions above for packages it is best practice to name a connection based on a logical name rather a database name or a server name. A database name can be volatile or meaningless like EGH275. So calling a connection DWH123.EGH275 is either wrong after the Go-live because the server name changed or could be meaningless like EGH275. A logical server name could be DWH and a logical database could be Frontroom which leads to DWHFrontoom or DWHWork.

{Logical Server Name} {Layer}

Variables

Variables in SSIS can be described with a name, a name space and a context. The context is the world were the variable exists in, typically an SSIS container. So variables are context specific or global. The default name space for a variable is called User.

I use the name space to describe the main purpose for using the variable. Is it a variable to override connection strings? Is it a counter in an For-Each-Loop-Container? I found at least three name spaces:

  • User – holds mostly context specific variables
  • Config – holds variables which overloads package or task properties and is more global
  • Result – holds variables with information for further processing inside or outside the package. These variables are mostly global.

The variable name is highly specific. So the only advice I can give is to use lowerCamelCase.

Control and Data Flow Items

The name of a task or container is comparable with the name of a function or procedure. For example the function name Math.Add imply that it can add two numbers. A Task name should do also.

I often use the WhoN’How-Where-What-Pattern for Data Flow Items. For example a data source (Who?) which loads accounting periods (What?) from the Work-Layer (Where?) in the ABCD-Table (Where?) is called:


Using CamelCase here would lead us to SrcWorkAbcdAccountingPeriod but this is too illegible. See here another example. A Lookup-Component. Proof it … what is done here?


This name gives us the following information: A full cache lookup onto the ShippingAddress table in the Extract-Layer with the IDShipAddr key column which returns the StrName column named as Street. It is very long eeh? Of course it is, but having a meaningful name is better than having a non-meaningful name. Every time I see packages without naming conventions the first thing I do is to rename the items inside to get the big picture.

Conclusion

In this article I covered naming conventions for control and data flow items as well as for packages, connections and variables. Feel free to make comments and suggestions on how to name things and please keep in mind: It is not important which naming convention you use. It is important that you use a naming convention.

  • Share/Bookmark

Templating-Mechanismus für Integration-Service-Pakete (Update SQL Server 2012)

Daniel Esser
Update für SQL Server 2012 (16.03.2012)

Die RTM Version des SQL Server 2012 ist gerade draußen und einige Fragen sich bereits ob das generieren von Pakten unter der Version 2012 immer noch funktioniert, schließlich hat sich das Paketformat drastisch verändert.

Die Antwort lautet ja. Allerdings sind die Integration Service Assemblies auf die CLR Version 4 angehoben worden. Solltet Ihr nun versuchen das ManagedDTS Assembly zu laden bekommt ihr folgende Fehlermeldung.

This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x8013101B)

Dies liegt daran, dass die Powershell 2.0 keine CLR 4 Assemblies laden kann (nur bis CLR 3.5). Glücklicherweise gibt es schon die PowerShell 3.0 CTP 2 oder richtiger das Windows Management Framework 3.0 CTP 2 welches PowerShell 3.0 beinhaltet. Mit PowerShell 3.0 ist es nun wieder möglich die entsprechenden Assemblies zu laden. Die Assemblies findet Ihr wie gewohnt unter:

C:\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies

Einführung

Es gibt vielerlei Gründe dafür ein SSIS-Template-Paket zu erstellen. In der Regel möchte man die Konfiguration über die Vielzahl der Paket in einem Projekt homogen halten. Heterogenität in der Paketkonfiguration erhöht die Fehleranfälligkeit während der Bereitstellungsphase insgesamt. Zwar gibt es die Möglichkeit der Vererbung der Konfiguration für Unterpakete, allerdings führt das für den IS-Entwickler dazu, dass Pakete nicht mehr einzeln zu starten sind, da diesen Paketen die vererbte Konfiguration des Elternpakts fehlt. Diese Einschränkung ist für die Entwicklung nicht hinnehmbar.

Um diese Einschränkung zu umgehen, muss jedes Paket einzeln Konfiguriert werden. Diese Arbeit manuell zu machen erhöht wieder die Fehleeanfälligkeit für die Bereitstellungsphase. So liegt der logische Schluss der Automatisierung recht nahe.

Nun gibt es unzählige Möglichkeiten IS-Pakete automatisiert anzupassen. Eine Möglichkeit wäre die Pakete durch einen XSLT-Prozessor zu jagen, die für die richtig Konfiguration sorgt. Das hätte den Charm, dass man für verschiedene Bereitstelllungszenarien verschiedene XSLT-Stylesheets schreiben könnte, die die jeweilige Konfiguration für das entsprechende Endsystem berücksichtigt. Der Nachteil dieser Variante ist, dass das KnowHow für XSLT vorhanden sein muss. Außerdem geht XSLT nicht leicht von der Hand.

Ein andere Variante wäre ein .NET-Applikation zu entwerfen, welche mitteln des IS-Objektmodell die entsprechenden Pakte anpasst oder generiert. Der Nachteil hierbei wäre die fehlende Flexibilität während der Entwicklung. Schnelle Änderungen setzen eine Ressource mit C#-Kenntnissen und Visual Studio voraus.

Eine ähnlicher aber flexiblerer Ansatz wäre eine Skript-Sprache zu verwenden mit Zugang zur .NET-Welt. Die Möglichkeiten sind auch hier wieder vielfältig. Hier wären zu nennen: Visual Basic, PowerShell und Iron Python. Welche Skript-Sprache man verwendet ist eher eine Geschmackssache. Da ich das Erweitern von IS-Paketen um eine einheitliche Paketkonfiguration eher in der Bereitstellung verorten würde, würde ich PowerShell (wegen der Nähe zur Administration) den Vorzug geben.

Grundgerüst

Die erste Hürde, die es zu meisten gilt ist von recht langweiliger Natur. Standardmäßig können PowerShell-Skripte nicht direkt ausgeführt werden. Wenn man sich die Mächtigkeit der PoweShell bewusst macht, ist das verständlich.

Es gibt zwei Wege dieses Hürde zu nehmen. Zum einen können wir die Sicherheitsmaßnahmen für PowerShell-Skripte herunterfahren. Für eine Produktionsumgebung ist das nicht zu empfehlen, zu Entwicklungszwecken aber legitim. Mit folgendem Kommando wird die Sicherheitseinstellung ausgeschaltet.

Set-ExecutionPolicy Unrestricted

Für eine Produktionsumgebung müsste das Skript signiert werden und eine Vertrauensstellung dem Eigentümer gegenüber eingerichtet werden. Weitere Informationen hierzu finden sich hier:

Der nächste Schritt wäre PowerShell mit SSIS zu verheiraten. Dazu müssen Assemblies des SQL Servers geladen werden. Im Fall des SQL Server 2008 befinden sich diese Dateien im Verzeichnis C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies.

[Reflection.Assembly]::LoadFile(“…\Microsoft.SqlServer.DTSPipelineWrap.dll”)[Reflection.Assembly]::LoadFile(“…\Microsoft.SQLServer.ManagedDTS.dll”)

Nach diesem Schritt stehen einem alle Objekte des SSIS-Objektsmodells zur Verfügung. Der nächste Schritt ist nun sich eine SSIS-Applikationskontext zu besorgen, ein Paket zu erstellen bzw. zu öffnen, Änderungen vorzunehmen und diese wieder abzuspeichern. Hier ein Beispiel für ein Grundgerüst:

 

# SSIS-Kontext erstellen
$context = new-object Microsoft.SqlServer.Dts.Runtime.Application

# Neues Paket erstellen
$package = new-object Microsoft.SqlServer.Dts.Runtime.Package

# Paket nach eigenen Wünschen anpassen

# Aufräumen
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($package)[System.Runtime.Interopservices.Marshal]::ReleaseComObject($context)

Remove-Variable context
Remove-Variable package

Soll ein bereits vorhandenes Paket geöffnet werden müsste das Grundgerüst entsprechend angepasst werden:

$context.LoadPackage(“C:\TestPackage.dtsx”, $null, $false)

Variablen erstellen und/oder anpassen

Bei der Homogenisierung der Paketkonfiguration werden Variablen benötigt. Zum Beispiel können Variablen dazu verwendet werden bestimmte Connections über Expressions zu Parametrisieren. Hier ein einfaches Beispiel um dem Paket Variablen mit zu geben. Diese Variablen werden später mittels Expressions an eine Connection weitergegeben. Über diese Connection werden dann alle benötigten weiteren Connections und Variablen geladen.

$var = $package.Variables.Add(“AdminDBCatalog”, $false, “Config”, “AdminDB”)
$var = $package.Variables.Add(“AdminDBHostename”, $false, “Config”, “HOSTNAME”)

Paketkonfiguration einschalten

Wie die Connections und die Variablen ist auch die Paketkonfiguration über das Objekt-Modell zu erreichen. Der Einfachheit halber verzichte ich an dieser Stelle darauf zu überprüfen ob die Konfiguration bereits existiert. Auf das grundlegende Prinzip dabei gehe ich bei der Erstellung der Connections im nächsten Abschnitt ein.

Im folgenden erstelle ich eine Paketkonfiguration welche einen Katalog- und Hostnamen aus einer Environmentvariable läd. Später wird eine Connection dann mit den Inhalten der Variablen parametrisiert.

#Sicherstellen, dass die Paket-Konfiguration eingeschaltet ist
$package.EnableConfigurations = $true

# Katalog aus Envrironment-Variable laden
$config = $package.Configurations.Add()
$config.Name = “AdminDBCatalog”
$config.ConfigurationType = 2
$config.ConfigurationString =
“AdminDBCatalog”
$config.PackagePath =
“\Package.Variables[Config::AdminDBHostname].Properties[Value]”

# Katalog aus Envrironment-Variable laden
$config = $package.Configurations.Add()
$config.Name = “AdminDBHostname”
$config.ConfigurationType = 2
$config.ConfigurationString =
“AdminDBHostname”
$config.PackagePath =
“\Package.Variables[Config::AdminDBCatalog].Properties[Value]“

Connections erstellen oder anpassen

Wesentlicher Bestandteil einer Connection ist der Connection-String und der Connection-Type. Folgendes Beispiel zeigt die Erstellung einer einfachen OLEDB-Connection:

$conMgr = $package.Connections.Add(“OLEDB”)
$conMgr.Name = “AdminDB Connection”
$conMgr.ConnectionString = “Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=HOSTNAME;Auto Translate=False;”

Den Connection String bekommt man entweder über der Database Explorer des VS, mit dem SSIS-Designer oder von http://www.connectionstrings.com/. Den Connection Type könnt ihr mit folgendem Befehl ermitteln:

$context.ConnectionInfos | select ConnectionType

ConnectionType
————–
ODBC
FLATFILE
OLEDB
MULTIFILE
MSOLAP100
HTTP
FILE
ADO.NET
FTP
ADO
MULTIFLATFILE
EXCEL
SQLMOBILE
CACHE
MSMQ
SMTP
WMI
SMOServer

In der Regel wäre es für unser Vorhaben aber besser wenn auf das Vorhandensein der Connection geprüft und diese ggf. angepasst würde. Prüfen kann man diese wie folgt:

$ErrorActionPreference = “SilentlyContinue”
$connectionName = “AdminDB Connection”
$conMgr = $package.Connections.Item($connectionName)

# Im Fehlerfall Connection neu anlegen
if (!$?) {
$conMgr = $package.Connections.Add(“OLEDB”)
$conMgr.Name = $connectionName
}

# Connections String setzen
$conMgr.ConnectionString = “Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=ANDERESOURCE;Auto Translate=False;”

Diese Technik stellt sicher, dass die Connection angelegt wird oder wenn bereits vorhanden, angepasst wird. Im zweiten Schritt wird die Connection so mit Expressions parametrisiert, dass die Connection dynamisch von den beiden Enronmentvariablen AdminDBCatalog und AdminDBHost abhängt.

# Connection an die Paketkonfiguration koppeln
$conMgr.SetExpression(“InitialCatalog”, “@[Config::AdminDBCatalog]“)
$conMgr.SetExpression(“ServerName”, “@[Config::AdminDBHostname]“)

Speichern des Pakets

Gespeichert werden kann das Paket mit folgendem Kommando:

$context.SaveToXml(“C:\TestPaket.dtsx”, $null)

Fazit und Ausblick

Im weiteren Verlauf wäre es wohl Ratsam weitere Fehler abzufangen. Des weiteren müssten weitere Variablen und Connections hinzugefügt werden, die man über eine Konfigurationsdatenbank konfigurieren will. Zum Schluss müsste noch die Paketkonfiguration angepasst werden, so dass weitere Inhalte aus der Konfigurationsdatenbank in Variablen geladen werden.

Wie jedoch zu sehen ist kann man mit PoweShell-Skripten und relativ wenigen Zeilen einen kleinen IS-Paket-Generator schreiben der auch noch leicht zu verstehen und zu erweitern ist.

Die Arbeit für solch ein Skript hat man genau einmal. Sich bei jeder Änderung der Konfiguration oder der Implementierung neuer Pakete durch die Dialoge der Paketkonfiguration zu klicken ist recht mühsam, Fehleranfällig und zeitverschwenderisch.

  • Share/Bookmark

SSIS Goodie #1: Excel + SSIS + 64 bit = DTS_E_OLEDB_EXCEL_NOT_SUPPORTED ?

Daniel Esser

The current majority opinion is that the current Office OLEDB provider (Microsoft.ACE.OLEDB.12.0) and 64-Bit environment can’t work together. In fact there are some problems using the provider in a 64Bit environment. If you want to know how to use it in SSIS the right way read this article.

(continue reading…)

  • Share/Bookmark

BIDS Goodie #1: How to use macros with SSIS

Daniel Esser

Do you ever used macros in Visual Studio? You can do also in BIDS and SSIS…

(continue reading…)

  • Share/Bookmark

  • Kategorien

  • Copyright © ORAYLIS Blog. All rights reserved.