<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ORAYLIS Blog &#187; MS SSIS</title>
	<atom:link href="http://blog.oraylis.de/category/technologie/ssis/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.oraylis.de</link>
	<description>ORAYLIS - Einfach mehr Wissen</description>
	<lastBuildDate>Fri, 18 May 2012 09:46:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>SSIS Pattern: Naming Convention Part I</title>
		<link>http://blog.oraylis.de/2012/03/ssis-pattern-naming-convention-part-i/</link>
		<comments>http://blog.oraylis.de/2012/03/ssis-pattern-naming-convention-part-i/#comments</comments>
		<pubDate>Fri, 16 Mar 2012 10:10:15 +0000</pubDate>
		<dc:creator>Daniel Esser</dc:creator>
				<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Design Pattern]]></category>
		<category><![CDATA[ETL]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=958</guid>
		<description><![CDATA[<p>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 &#8220;Streets&#8221; and North-South streets called &#8220;Avenues&#8221;.</p>
<p>First we have to identify which entities have to be named in SSIS:</p>
<ul>
<li>Projects</li>
<li>Packages (filename and identification name)</li>
<li>Configurations</li>
<li>Loggers</li>
<li>Connections</li>
<li>Variables</li>
<li>Control Flow and Data Flow items</li>
</ul>
<p>Secondly it is not important <strong>which </strong>naming convention you use. It is important <strong>that </strong>you use a naming convention. There is a good article about naming conventions on <a href="http://en.wikipedia.org/wiki/Naming_conventions_%28programming%29">Wikipedia</a> you could use for inspiration. The CamelCase naming convention is often used in programming, so I decided to use it for the following examples.</p>
<p>Thirdly we need a clear and intuitive naming definition on <strong>how </strong>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?</p>
<h4>The Project Name</h4>
<p>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.</p>
<h4>The Package Name</h4>
<p>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&#8217;t exist.</p>
<p>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: <strong>Control</strong>, <strong>Load </strong>and execute <strong>functional </strong>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:</p>
<ul>
<li><em>Ctrl </em>for packages which controls the execution of other packages</li>
<li><em>Load </em>for packages which loads data</li>
<li><em>Func </em>for packages which do some functional things like sending mails etc. pp.</li>
</ul>
<p>Based on this we can go further. For <em>Ctrl </em>and <em>Func</em> 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:</p>
<ul>
<li><em>CtrlMaster </em>- A master control package for the whole project</li>
<li><em>CtrlCubeProcessing </em>- A package which calls other packages to process dimensions and cubes in a non default manner</li>
<li><em>FuncSendSuccMail </em>- Send a success mail to some people after processing cubes</li>
<li><em>FuncValidateMailAdresses </em>- A package which validates a table with mail addresses. It marks which are correct and which not.</li>
</ul>
<p>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.</p>
<ul>
<li><em>LoadExtract </em>- A package which loads data from an operative or external data source</li>
<li><em>LoadWork </em>- A package which modifies the loaded data from the Extraction-Layer</li>
<li><em>LoadFront </em>- A package which fills the Datawarehouse with data from the Work or Extraction-Layer</li>
</ul>
<p>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 <em>LoadFrontSalesDimCustomer </em>if the package fills the <em>Customer Dimension</em> for the <em>Sales Datawarehouse</em> which is stored in the Frontroom-Layer. The final naming definition for <em>Load</em>-Packages could be</p>
<p style="text-align: center"><em>&#8220;Load&#8221;</em> {Logical Layer} {Database Name or abbreviation} {Tablename/Dimension/Fact}</p>
<h4>Connections</h4>
<p>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 <em>Frontroom</em> which leads to <em>DWHFrontoom</em> or DWHWork.</p>
<p style="text-align: center">{<em>Logical Server Name</em>} {<em>Layer</em>}</p>
<h4 style="text-align: left">Variables</h4>
<p>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 <em>User</em>.</p>
<p>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:</p>
<ul>
<li><em>User &#8211; </em>holds mostly context specific variables</li>
<li><em>Config &#8211; </em>holds variables which overloads package or task properties and is more global</li>
<li><em>Result</em> &#8211; holds variables with information for further processing inside or outside the package. These variables are mostly global.</li>
</ul>
<p>The variable name is highly specific. So the only advice I can give is to use lowerCamelCase.</p>
<h4>Control and Data Flow Items</h4>
<p>The name of a task or container is comparable with the name of a function or procedure. For example the function name <em>Math.Add</em> imply that it can add two numbers. A Task name should do also.</p>
<p>I often use the <em>WhoN&#8217;How-Where-What</em>-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:</p>
<p style="text-align: center"><em><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/SrcExample.png"><img class="aligncenter size-full wp-image-968" src="http://blog.oraylis.de/wp-content/uploads/2011/02/SrcExample.png" alt="" width="254" height="44" /></a><br />
</em></p>
<p style="text-align: left">Using <em>CamelCase </em>here would lead us to <em>SrcWorkAbcdAccountingPeriod</em> but this is too illegible. See here another example. A Lookup-Component. Proof it &#8230; what is done here?</p>
<p style="text-align: center"><em><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/LookupExample.png"><img class="aligncenter size-full wp-image-969" src="http://blog.oraylis.de/wp-content/uploads/2011/02/LookupExample.png" alt="" width="422" height="44" /></a><br />
</em></p>
<p style="text-align: left">This name gives us the following information: A <strong>full </strong>cache <strong>lookup </strong>onto the <strong>ShippingAddress table </strong>in the <strong>Extract-Layer</strong> with the <strong>IDShipAddr key column</strong> which returns the <strong>StrName column</strong> named as <strong>Street</strong>. 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.</p>
<h4 style="text-align: left">Conclusion</h4>
<p style="text-align: left">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 <strong>which </strong>naming convention you use. It is important <strong>that </strong>you use a naming convention.</p>
<p style="text-align: left">
<div style="display:block"><small><em>by Daniel Esser <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2012%2F03%2Fssis-pattern-naming-convention-part-i%2F&amp;linkname=SSIS%20Pattern%3A%20Naming%20Convention%20Part%20I"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>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 &#8220;Streets&#8221; and North-South streets called &#8220;Avenues&#8221;.</p>
<p>First we have to identify which entities have to be named in SSIS:</p>
<ul>
<li>Projects</li>
<li>Packages (filename and identification name)</li>
<li>Configurations</li>
<li>Loggers</li>
<li>Connections</li>
<li>Variables</li>
<li>Control Flow and Data Flow items</li>
</ul>
<p>Secondly it is not important <strong>which </strong>naming convention you use. It is important <strong>that </strong>you use a naming convention. There is a good article about naming conventions on <a href="http://en.wikipedia.org/wiki/Naming_conventions_%28programming%29">Wikipedia</a> you could use for inspiration. The CamelCase naming convention is often used in programming, so I decided to use it for the following examples.</p>
<p>Thirdly we need a clear and intuitive naming definition on <strong>how </strong>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?</p>
<h4>The Project Name</h4>
<p>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.</p>
<h4>The Package Name</h4>
<p>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&#8217;t exist.</p>
<p>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: <strong>Control</strong>, <strong>Load </strong>and execute <strong>functional </strong>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:</p>
<ul>
<li><em>Ctrl </em>for packages which controls the execution of other packages</li>
<li><em>Load </em>for packages which loads data</li>
<li><em>Func </em>for packages which do some functional things like sending mails etc. pp.</li>
</ul>
<p>Based on this we can go further. For <em>Ctrl </em>and <em>Func</em> 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:</p>
<ul>
<li><em>CtrlMaster </em>- A master control package for the whole project</li>
<li><em>CtrlCubeProcessing </em>- A package which calls other packages to process dimensions and cubes in a non default manner</li>
<li><em>FuncSendSuccMail </em>- Send a success mail to some people after processing cubes</li>
<li><em>FuncValidateMailAdresses </em>- A package which validates a table with mail addresses. It marks which are correct and which not.</li>
</ul>
<p>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.</p>
<ul>
<li><em>LoadExtract </em>- A package which loads data from an operative or external data source</li>
<li><em>LoadWork </em>- A package which modifies the loaded data from the Extraction-Layer</li>
<li><em>LoadFront </em>- A package which fills the Datawarehouse with data from the Work or Extraction-Layer</li>
</ul>
<p>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 <em>LoadFrontSalesDimCustomer </em>if the package fills the <em>Customer Dimension</em> for the <em>Sales Datawarehouse</em> which is stored in the Frontroom-Layer. The final naming definition for <em>Load</em>-Packages could be</p>
<p style="text-align: center"><em>&#8220;Load&#8221;</em> {Logical Layer} {Database Name or abbreviation} {Tablename/Dimension/Fact}</p>
<h4>Connections</h4>
<p>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 <em>Frontroom</em> which leads to <em>DWHFrontoom</em> or DWHWork.</p>
<p style="text-align: center">{<em>Logical Server Name</em>} {<em>Layer</em>}</p>
<h4 style="text-align: left">Variables</h4>
<p>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 <em>User</em>.</p>
<p>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:</p>
<ul>
<li><em>User &#8211; </em>holds mostly context specific variables</li>
<li><em>Config &#8211; </em>holds variables which overloads package or task properties and is more global</li>
<li><em>Result</em> &#8211; holds variables with information for further processing inside or outside the package. These variables are mostly global.</li>
</ul>
<p>The variable name is highly specific. So the only advice I can give is to use lowerCamelCase.</p>
<h4>Control and Data Flow Items</h4>
<p>The name of a task or container is comparable with the name of a function or procedure. For example the function name <em>Math.Add</em> imply that it can add two numbers. A Task name should do also.</p>
<p>I often use the <em>WhoN&#8217;How-Where-What</em>-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:</p>
<p style="text-align: center"><em><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/SrcExample.png"><img class="aligncenter size-full wp-image-968" src="http://blog.oraylis.de/wp-content/uploads/2011/02/SrcExample.png" alt="" width="254" height="44" /></a><br />
</em></p>
<p style="text-align: left">Using <em>CamelCase </em>here would lead us to <em>SrcWorkAbcdAccountingPeriod</em> but this is too illegible. See here another example. A Lookup-Component. Proof it &#8230; what is done here?</p>
<p style="text-align: center"><em><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/LookupExample.png"><img class="aligncenter size-full wp-image-969" src="http://blog.oraylis.de/wp-content/uploads/2011/02/LookupExample.png" alt="" width="422" height="44" /></a><br />
</em></p>
<p style="text-align: left">This name gives us the following information: A <strong>full </strong>cache <strong>lookup </strong>onto the <strong>ShippingAddress table </strong>in the <strong>Extract-Layer</strong> with the <strong>IDShipAddr key column</strong> which returns the <strong>StrName column</strong> named as <strong>Street</strong>. 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.</p>
<h4 style="text-align: left">Conclusion</h4>
<p style="text-align: left">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 <strong>which </strong>naming convention you use. It is important <strong>that </strong>you use a naming convention.</p>
<p style="text-align: left">
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2012/03/ssis-pattern-naming-convention-part-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Templating-Mechanismus für Integration-Service-Pakete (Update SQL Server 2012)</title>
		<link>http://blog.oraylis.de/2012/03/templating-mechanismus-fr-integration-service-pakete/</link>
		<comments>http://blog.oraylis.de/2012/03/templating-mechanismus-fr-integration-service-pakete/#comments</comments>
		<pubDate>Fri, 16 Mar 2012 09:00:31 +0000</pubDate>
		<dc:creator>Daniel Esser</dc:creator>
				<category><![CDATA[Microsoft BI]]></category>
		<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Test Tools]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=865</guid>
		<description><![CDATA[<h5><span style="text-decoration: underline">Update für SQL Server 2012 (16.03.2012)</span></h5>
<p>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.</p>
<p>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.</p>
<p style="text-align: center"><em>This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x8013101B)</em></p>
<p>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 <a href="http://www.microsoft.com/download/en/details.aspx?id=27548" target="_blank">Windows Management Framework 3.0 CTP 2</a> 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:</p>
<p style="text-align: center"><em>C:\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies</em></p>
<h5>Einführung</h5>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h5>Grundgerüst</h5>
<p>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.</p>
<p>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 <strong>nicht</strong> zu empfehlen, zu Entwicklungszwecken aber legitim. Mit folgendem Kommando wird die Sicherheitseinstellung ausgeschaltet.</p>
<p><span style="font-family: Courier New"><span style="color: #9b00d3">Set-ExecutionPolicy</span> Unrestricted</span></p>
<p>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:</p>
<ul>
<li><a title="http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/" href="http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/">http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/</a></li>
</ul>
<p>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 <span style="font-family: Courier New">C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies</span>.</p>
<p><span style="font-family: Courier New">[Reflection.Assembly]::LoadFile(<span style="color: #cccccc">&#8220;&#8230;\Microsoft.SqlServer.DTSPipelineWrap.dll&#8221;</span>)[Reflection.Assembly]::LoadFile(<span style="color: #cccccc">&#8220;&#8230;\Microsoft.SQLServer.ManagedDTS.dll&#8221;</span>)</span></p>
<p>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:</p>
<p>&nbsp;</p>
<p><span style="font-family: Courier New"><span style="color: #008040"># SSIS-Kontext erstellen</span><br />
<strong>$context</strong> = <span style="color: #9b00d3">new-object</span> Microsoft.SqlServer.Dts.Runtime.Application </span></p>
<p><span style="font-family: Courier New"><span style="color: #008040"># Neues Paket erstellen<br />
</span><strong>$package</strong> = <span style="color: #9b00d3">new-object</span> Microsoft.SqlServer.Dts.Runtime.Package </span></p>
<p><span style="font-family: Courier New"><span style="color: #008040"># Paket nach eigenen Wünschen anpassen<br />
</span><br />
<span style="color: #008040"># Aufräumen</span><br />
[System.Runtime.Interopservices.Marshal]::ReleaseComObject(<strong>$package</strong>)[System.Runtime.Interopservices.Marshal]::ReleaseComObject(<strong>$context</strong>) </span></p>
<p><span style="font-family: Courier New"><span style="color: #9b00d3">Remove-Variable</span> context<br />
<span style="color: #9b00d3">Remove-Variable</span> package</span></p>
<p>Soll ein bereits vorhandenes Paket geöffnet werden müsste das Grundgerüst entsprechend angepasst werden:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.LoadPackage<span style="color: #cccccc">(&#8220;C:\TestPackage.dtsx&#8221;</span>, <strong>$null</strong>, <strong>$false</strong>)</span></p>
<h5>Variablen erstellen und/oder anpassen</h5>
<p>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.</p>
<p><span style="font-family: Courier New"><strong>$var</strong> = <strong>$package</strong>.Variables.Add(<span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;</span>, <strong>$false</strong>, <span style="color: #cccccc">&#8220;Config&#8221;</span>, <span style="color: #cccccc">&#8220;AdminDB&#8221;</span>)<br />
<strong>$var</strong> = <strong>$package</strong>.Variables.Add(<span style="color: #cccccc">&#8220;AdminDBHostename&#8221;</span>, <strong>$false</strong>, <span style="color: #cccccc">&#8220;Config&#8221;</span>, <span style="color: #cccccc">&#8220;HOSTNAME&#8221;</span>)</span></p>
<h5>Paketkonfiguration einschalten</h5>
<p>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.</p>
<p>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.</p>
<p><span style="font-family: Courier New"><span style="color: #008000">#Sicherstellen, dass die Paket-Konfiguration eingeschaltet ist<br />
</span><strong>$package</strong>.EnableConfigurations = <strong>$true</strong> </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Katalog aus Envrironment-Variable laden </span></span><span style="font-family: Courier New"><br />
<strong>$config </strong>= <strong>$package</strong>.Configurations.Add()<br />
<strong>$config</strong>.Name = <span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;<br />
</span></span><span style="font-family: Courier New"><strong>$config</strong>.ConfigurationType = <span style="color: #ffc000">2</span><br />
<strong>$config</strong>.ConfigurationString = </span><span style="font-family: Courier New"><span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;<br />
</span><strong>$config</strong>.PackagePath = </span><span style="font-family: Courier New;color: #cccccc">&#8220;\Package.Variables[Config::AdminDBHostname].Properties[Value]&#8221; </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Katalog aus Envrironment-Variable laden<br />
</span></span><strong><span style="font-family: Courier New">$config</span></strong><span style="font-family: Courier New"> = <strong>$package</strong>.Configurations.Add()<br />
<strong>$config</strong>.Name = <span style="color: #cccccc">&#8220;AdminDBHostname&#8221;</span><br />
</span><span style="font-family: Courier New"><strong>$config</strong>.ConfigurationType = <span style="color: #ffc000">2</span><br />
$config.ConfigurationString = </span><span style="font-family: Courier New"><span style="color: #cccccc">&#8220;AdminDBHostname&#8221;<br />
</span>$config.PackagePath = </span><span style="color: #cccccc"><span style="font-family: Courier New">&#8220;\Package.Variables[Config::AdminDBCatalog].Properties[Value]&#8220;</span> </span></p>
<h5>Connections erstellen oder anpassen</h5>
<p>Wesentlicher Bestandteil einer Connection ist der Connection-String und der Connection-Type. Folgendes Beispiel zeigt die Erstellung einer einfachen OLEDB-Connection:</p>
<p><span style="font-family: Courier New"><strong>$conMgr</strong> = <strong>$package</strong>.Connections.Add(<span style="color: #cccccc">&#8220;OLEDB&#8221;</span>)<br />
<strong>$conMgr</strong>.Name = <span style="color: #cccccc">&#8220;AdminDB Connection&#8221;</span><br />
<strong>$conMgr</strong>.ConnectionString = <span style="color: #cccccc">&#8220;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=HOSTNAME;Auto Translate=False;&#8221;</span></span></p>
<p>Den Connection String bekommt man entweder über der Database Explorer des VS, mit dem SSIS-Designer oder von <a title="http://www.connectionstrings.com/" href="http://www.connectionstrings.com/">http://www.connectionstrings.com/</a>. Den Connection Type könnt ihr mit folgendem Befehl ermitteln:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.ConnectionInfos <span style="color: #9b00d3">|</span> <span style="color: #0000ff">select</span> ConnectionType<br />
</span><br />
<span style="font-family: Courier New">ConnectionType<br />
&#8212;&#8212;&#8212;&#8212;&#8211;<br />
ODBC<br />
FLATFILE<br />
OLEDB<br />
MULTIFILE<br />
MSOLAP100<br />
HTTP<br />
FILE<br />
ADO.NET<br />
FTP<br />
ADO<br />
MULTIFLATFILE<br />
EXCEL<br />
SQLMOBILE<br />
CACHE<br />
MSMQ<br />
SMTP<br />
WMI<br />
SMOServer</span></p>
<p>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:</p>
<p><span style="font-family: Courier New"><strong>$ErrorActionPreference</strong> = <span style="color: #cccccc">&#8220;SilentlyContinue&#8221; </span><br />
<strong>$connectionName</strong> = <span style="color: #cccccc">&#8220;AdminDB Connection&#8221;</span><br />
<strong>$conMgr</strong> =<strong> $package</strong>.Connections.Item(<strong>$connectionName</strong>) </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Im Fehlerfall Connection neu anlegen</span><br />
<span style="color: #0000ff">if</span> (<strong>!$?</strong>) {<br />
<strong> $conMgr</strong> = <strong>$package</strong>.Connections.Add(<span style="color: #cccccc">&#8220;OLEDB&#8221;</span>)<br />
<strong> $conMgr</strong>.Name = <strong>$connectionName</strong><br />
}<br />
</span><span style="color: #008000"><br />
<span style="font-family: Courier New"># Connections String setzen<br />
</span></span><span style="font-family: Courier New"><strong>$conMgr</strong>.ConnectionString = <span style="color: #cccccc">&#8220;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=<span style="color: #ff0000">ANDERESOURCE</span>;Auto Translate=False;&#8221;</span></span></p>
<p><span style="font-family: Courier New"><span style="font-family: Verdana">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.</span> </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Connection an die Paketkonfiguration koppeln</span><br />
<strong>$conMgr</strong>.SetExpression(<span style="color: #cccccc">&#8220;InitialCatalog&#8221;</span>, <span style="color: #cccccc">&#8220;@[Config::AdminDBCatalog]&#8220;</span>)<br />
<strong>$conMgr</strong>.SetExpression(<span style="color: #cccccc">&#8220;ServerName&#8221;</span>, <span style="color: #cccccc">&#8220;@[Config::AdminDBHostname]&#8220;</span>)</span></p>
<h5>Speichern des Pakets</h5>
<p>Gespeichert werden kann das Paket mit folgendem Kommando:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.SaveToXml(<span style="color: #cccccc">&#8220;C:\TestPaket.dtsx&#8221;</span>, <strong>$null</strong>)</span></p>
<h5>Fazit und Ausblick</h5>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<div style="display:block"><small><em>by Daniel Esser <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2012%2F03%2Ftemplating-mechanismus-fr-integration-service-pakete%2F&amp;linkname=Templating-Mechanismus%20f%C3%BCr%20Integration-Service-Pakete%20%28Update%20SQL%20Server%202012%29"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<h5><span style="text-decoration: underline">Update für SQL Server 2012 (16.03.2012)</span></h5>
<p>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.</p>
<p>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.</p>
<p style="text-align: center"><em>This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x8013101B)</em></p>
<p>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 <a href="http://www.microsoft.com/download/en/details.aspx?id=27548" target="_blank">Windows Management Framework 3.0 CTP 2</a> 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:</p>
<p style="text-align: center"><em>C:\Program Files (x86)\Microsoft SQL Server\110\SDK\Assemblies</em></p>
<h5>Einführung</h5>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h5>Grundgerüst</h5>
<p>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.</p>
<p>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 <strong>nicht</strong> zu empfehlen, zu Entwicklungszwecken aber legitim. Mit folgendem Kommando wird die Sicherheitseinstellung ausgeschaltet.</p>
<p><span style="font-family: Courier New"><span style="color: #9b00d3">Set-ExecutionPolicy</span> Unrestricted</span></p>
<p>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:</p>
<ul>
<li><a title="http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/" href="http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/">http://www.scriptinganswers.com/essentials/index.php/2008/02/21/how-do-i-sign-a-windows-powershell-script/</a></li>
</ul>
<p>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 <span style="font-family: Courier New">C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies</span>.</p>
<p><span style="font-family: Courier New">[Reflection.Assembly]::LoadFile(<span style="color: #cccccc">&#8220;&#8230;\Microsoft.SqlServer.DTSPipelineWrap.dll&#8221;</span>)[Reflection.Assembly]::LoadFile(<span style="color: #cccccc">&#8220;&#8230;\Microsoft.SQLServer.ManagedDTS.dll&#8221;</span>)</span></p>
<p>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:</p>
<p>&nbsp;</p>
<p><span style="font-family: Courier New"><span style="color: #008040"># SSIS-Kontext erstellen</span><br />
<strong>$context</strong> = <span style="color: #9b00d3">new-object</span> Microsoft.SqlServer.Dts.Runtime.Application </span></p>
<p><span style="font-family: Courier New"><span style="color: #008040"># Neues Paket erstellen<br />
</span><strong>$package</strong> = <span style="color: #9b00d3">new-object</span> Microsoft.SqlServer.Dts.Runtime.Package </span></p>
<p><span style="font-family: Courier New"><span style="color: #008040"># Paket nach eigenen Wünschen anpassen<br />
</span><br />
<span style="color: #008040"># Aufräumen</span><br />
[System.Runtime.Interopservices.Marshal]::ReleaseComObject(<strong>$package</strong>)[System.Runtime.Interopservices.Marshal]::ReleaseComObject(<strong>$context</strong>) </span></p>
<p><span style="font-family: Courier New"><span style="color: #9b00d3">Remove-Variable</span> context<br />
<span style="color: #9b00d3">Remove-Variable</span> package</span></p>
<p>Soll ein bereits vorhandenes Paket geöffnet werden müsste das Grundgerüst entsprechend angepasst werden:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.LoadPackage<span style="color: #cccccc">(&#8220;C:\TestPackage.dtsx&#8221;</span>, <strong>$null</strong>, <strong>$false</strong>)</span></p>
<h5>Variablen erstellen und/oder anpassen</h5>
<p>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.</p>
<p><span style="font-family: Courier New"><strong>$var</strong> = <strong>$package</strong>.Variables.Add(<span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;</span>, <strong>$false</strong>, <span style="color: #cccccc">&#8220;Config&#8221;</span>, <span style="color: #cccccc">&#8220;AdminDB&#8221;</span>)<br />
<strong>$var</strong> = <strong>$package</strong>.Variables.Add(<span style="color: #cccccc">&#8220;AdminDBHostename&#8221;</span>, <strong>$false</strong>, <span style="color: #cccccc">&#8220;Config&#8221;</span>, <span style="color: #cccccc">&#8220;HOSTNAME&#8221;</span>)</span></p>
<h5>Paketkonfiguration einschalten</h5>
<p>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.</p>
<p>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.</p>
<p><span style="font-family: Courier New"><span style="color: #008000">#Sicherstellen, dass die Paket-Konfiguration eingeschaltet ist<br />
</span><strong>$package</strong>.EnableConfigurations = <strong>$true</strong> </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Katalog aus Envrironment-Variable laden </span></span><span style="font-family: Courier New"><br />
<strong>$config </strong>= <strong>$package</strong>.Configurations.Add()<br />
<strong>$config</strong>.Name = <span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;<br />
</span></span><span style="font-family: Courier New"><strong>$config</strong>.ConfigurationType = <span style="color: #ffc000">2</span><br />
<strong>$config</strong>.ConfigurationString = </span><span style="font-family: Courier New"><span style="color: #cccccc">&#8220;AdminDBCatalog&#8221;<br />
</span><strong>$config</strong>.PackagePath = </span><span style="font-family: Courier New;color: #cccccc">&#8220;\Package.Variables[Config::AdminDBHostname].Properties[Value]&#8221; </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Katalog aus Envrironment-Variable laden<br />
</span></span><strong><span style="font-family: Courier New">$config</span></strong><span style="font-family: Courier New"> = <strong>$package</strong>.Configurations.Add()<br />
<strong>$config</strong>.Name = <span style="color: #cccccc">&#8220;AdminDBHostname&#8221;</span><br />
</span><span style="font-family: Courier New"><strong>$config</strong>.ConfigurationType = <span style="color: #ffc000">2</span><br />
$config.ConfigurationString = </span><span style="font-family: Courier New"><span style="color: #cccccc">&#8220;AdminDBHostname&#8221;<br />
</span>$config.PackagePath = </span><span style="color: #cccccc"><span style="font-family: Courier New">&#8220;\Package.Variables[Config::AdminDBCatalog].Properties[Value]&#8220;</span> </span></p>
<h5>Connections erstellen oder anpassen</h5>
<p>Wesentlicher Bestandteil einer Connection ist der Connection-String und der Connection-Type. Folgendes Beispiel zeigt die Erstellung einer einfachen OLEDB-Connection:</p>
<p><span style="font-family: Courier New"><strong>$conMgr</strong> = <strong>$package</strong>.Connections.Add(<span style="color: #cccccc">&#8220;OLEDB&#8221;</span>)<br />
<strong>$conMgr</strong>.Name = <span style="color: #cccccc">&#8220;AdminDB Connection&#8221;</span><br />
<strong>$conMgr</strong>.ConnectionString = <span style="color: #cccccc">&#8220;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=HOSTNAME;Auto Translate=False;&#8221;</span></span></p>
<p>Den Connection String bekommt man entweder über der Database Explorer des VS, mit dem SSIS-Designer oder von <a title="http://www.connectionstrings.com/" href="http://www.connectionstrings.com/">http://www.connectionstrings.com/</a>. Den Connection Type könnt ihr mit folgendem Befehl ermitteln:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.ConnectionInfos <span style="color: #9b00d3">|</span> <span style="color: #0000ff">select</span> ConnectionType<br />
</span><br />
<span style="font-family: Courier New">ConnectionType<br />
&#8212;&#8212;&#8212;&#8212;&#8211;<br />
ODBC<br />
FLATFILE<br />
OLEDB<br />
MULTIFILE<br />
MSOLAP100<br />
HTTP<br />
FILE<br />
ADO.NET<br />
FTP<br />
ADO<br />
MULTIFLATFILE<br />
EXCEL<br />
SQLMOBILE<br />
CACHE<br />
MSMQ<br />
SMTP<br />
WMI<br />
SMOServer</span></p>
<p>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:</p>
<p><span style="font-family: Courier New"><strong>$ErrorActionPreference</strong> = <span style="color: #cccccc">&#8220;SilentlyContinue&#8221; </span><br />
<strong>$connectionName</strong> = <span style="color: #cccccc">&#8220;AdminDB Connection&#8221;</span><br />
<strong>$conMgr</strong> =<strong> $package</strong>.Connections.Item(<strong>$connectionName</strong>) </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Im Fehlerfall Connection neu anlegen</span><br />
<span style="color: #0000ff">if</span> (<strong>!$?</strong>) {<br />
<strong> $conMgr</strong> = <strong>$package</strong>.Connections.Add(<span style="color: #cccccc">&#8220;OLEDB&#8221;</span>)<br />
<strong> $conMgr</strong>.Name = <strong>$connectionName</strong><br />
}<br />
</span><span style="color: #008000"><br />
<span style="font-family: Courier New"># Connections String setzen<br />
</span></span><span style="font-family: Courier New"><strong>$conMgr</strong>.ConnectionString = <span style="color: #cccccc">&#8220;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdminDB;Data Source=<span style="color: #ff0000">ANDERESOURCE</span>;Auto Translate=False;&#8221;</span></span></p>
<p><span style="font-family: Courier New"><span style="font-family: Verdana">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.</span> </span></p>
<p><span style="font-family: Courier New"><span style="color: #008000"># Connection an die Paketkonfiguration koppeln</span><br />
<strong>$conMgr</strong>.SetExpression(<span style="color: #cccccc">&#8220;InitialCatalog&#8221;</span>, <span style="color: #cccccc">&#8220;@[Config::AdminDBCatalog]&#8220;</span>)<br />
<strong>$conMgr</strong>.SetExpression(<span style="color: #cccccc">&#8220;ServerName&#8221;</span>, <span style="color: #cccccc">&#8220;@[Config::AdminDBHostname]&#8220;</span>)</span></p>
<h5>Speichern des Pakets</h5>
<p>Gespeichert werden kann das Paket mit folgendem Kommando:</p>
<p><span style="font-family: Courier New"><strong>$context</strong>.SaveToXml(<span style="color: #cccccc">&#8220;C:\TestPaket.dtsx&#8221;</span>, <strong>$null</strong>)</span></p>
<h5>Fazit und Ausblick</h5>
<p>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.</p>
<p>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.</p>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2012/03/templating-mechanismus-fr-integration-service-pakete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parallel hierarchies in a parent-child structure</title>
		<link>http://blog.oraylis.de/2011/07/parallel-hierarchies-in-a-parent-child-structure/</link>
		<comments>http://blog.oraylis.de/2011/07/parallel-hierarchies-in-a-parent-child-structure/#comments</comments>
		<pubDate>Sat, 30 Jul 2011 11:33:30 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[Parent Child]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/07/parallel-hierarchies-in-a-parent-child-structure/</guid>
		<description><![CDATA[<p align="right">SQL Server 2005 | SQL Server 2008 | SQL Server 2008R2</p>
<p>This post is about a problem I faced some years ago. The source system was SAP with user defined hierarchies, in this case within the cost center and cost type tables. Parallel hierarchies are well supported in SQL Server BI but in this case, users in SAP could define multiple hierarchies on their own and they wanted these hierarchies to be also available in the OLAP cube. For example, costs associated with the cost center 1000 should be analyzed as shown below:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy" border="0" alt="hierarchy" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy_thumb.png" width="344" height="224" /></a></p>
<p>All costs that are booked on cost center 1000 have to appear in the hierarchy as shown in the sketch. And end-users may also be able to create new hierarchies (for example to analyze a certain project). Of course there may be better ways to model this but in this case we had basically two tables for the cost centers:</p>
<ul>
<li>table CC (Cost Center) </li>
<li>table CCG (Cost Center Group) </li>
</ul>
<p>Table CC contains all cost centers (for example the above cost center 1000) together with additional information (like name, responsible person etc.) while table CCG contains the hierarchy. in CCG we basically find two columns:</p>
<ul>
<li>Node name </li>
<li>Parent node name </li>
</ul>
<table border="1" cellspacing="0" cellpadding="2" width="340">
<tbody>
<tr>
<td valign="top" width="171"><strong>Node</strong></td>
<td valign="top" width="167"><strong>Parent Node</strong></td>
</tr>
<tr>
<td valign="top" width="171">1000</td>
<td valign="top" width="167">Internal_HR_DE</td>
</tr>
<tr>
<td valign="top" width="171">Internal_HR_DE</td>
<td valign="top" width="167">HR_DE</td>
</tr>
<tr>
<td valign="top" width="171">HR_DE</td>
<td valign="top" width="167">Germany</td>
</tr>
<tr>
<td valign="top" width="171">1000</td>
<td valign="top" width="167">Marketing_DE</td>
</tr>
<tr>
<td valign="top" width="171">Marketing_DE</td>
<td valign="top" width="167">Germany</td>
</tr>
<tr>
<td valign="top" width="171">Germany</td>
<td valign="top" width="167">Corporate</td>
</tr>
<tr>
<td valign="top" width="171">Marketing_DE</td>
<td valign="top" width="167">Marketing</td>
</tr>
<tr>
<td valign="top" width="171">Marketing</td>
<td valign="top" width="167">Corporate</td>
</tr>
</tbody>
</table>
<p>Facts (in this case actual or planned costs) are associated with the cost center number (for example 1000). Usually, parent-child hierarchies may be used in this case where we have a very dynamic structure and we do not know the number of levels. However, parent-child may only be used if each node has at most one parent. But here we find the cost center 1000 having two parents (Internal HR Costs DE and Marketing_DE). The same situation exists with the Marketing_DE node (having parents Marketing and Germany).</p>
<p>The solution I’m presenting here is to create additional nodes until each node only has one parent. This is possible as each node of a parent-child hierarchy in SSAS has a name and a key property. So, the name will be identical, while the key will be different. In order to show the process, let’s add internal keys to each of the hierarchy elements.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy1" border="0" alt="hierarchy1" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy1_thumb.png" width="322" height="248" /></a></p>
<p>What we have to do now is to create additional nodes for every node that has more than one parent. Let’s start with the ‘Marketing_DE’ node:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy2" border="0" alt="hierarchy2" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy2_thumb.png" width="402" height="226" /></a></p>
<p>The additional node gets a new (internal) key, in this example the number 8. But there is still a node with multiple parents: the cost center 1000. Let’s also transform this into separate nodes:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy3" border="0" alt="hierarchy3" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy3_thumb.png" width="400" height="217" /></a></p>
<p>After this step, each node has at most one parent and therefore the structure can be modeled as an SSAS parent-child hierarchy.&#160; </p>
<p>But now, we have to think about the fact rows. Without the hierarchy, facts would have been associated to the cost center by using the internal key (surrogate key), so for example 1000 € that are booked on cost center 1000 would appear in the fact table like</p>
<table border="1" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td valign="top" width="125"><strong>DateKey</strong></td>
<td valign="top" width="125"><strong>CostCenterKey</strong></td>
<td valign="top" width="125"><strong>…</strong></td>
<td valign="top" width="125"><strong>Amount</strong></td>
</tr>
<tr>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
</tr>
<tr>
<td valign="top" width="125">20110630</td>
<td valign="top" width="125">1</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">1000</td>
</tr>
<tr>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
</tr>
</tbody>
</table>
<p>But now, we have to associate this single fact row to three rows in the dimension table (as the cost center 1000 appears three times now). Therefore we have to use a many-to-many approach, so we add another table, a so called bridge table with the following rows:</p>
<table border="1" cellspacing="0" cellpadding="2" width="290">
<tbody>
<tr>
<td valign="top" width="136"><strong>CostCenterKey</strong></td>
<td valign="top" width="152"><strong>CostCenterDimKey</strong></td>
</tr>
<tr>
<td valign="top" width="136">…</td>
<td valign="top" width="152">…</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">1</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">9</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">10</td>
</tr>
<tr>
<td valign="top" width="136">…</td>
<td valign="top" width="152">…</td>
</tr>
</tbody>
</table>
<p>For technical reasons, our fact table has to be linked to a dimension (of flat cost centers), which is also used by the bridge table. This is shown in the following image:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy4" border="0" alt="hierarchy4" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy4_thumb.png" width="486" height="114" /></a></p>
<p>The most difficult part here is to “normalize” the parent-child structure. One way to do this is to use a stored procedure. Here is the code I used. Within this procedure, the following tables are used:</p>
<table border="1" cellspacing="0" cellpadding="2" width="658">
<tbody>
<tr>
<td valign="top" width="250">masterdata.Costcenter</td>
<td valign="top" width="406">the flat table of cost centers (only leaf-level). The key field is the cost center number (for example 1000 for our cost center from above)</td>
</tr>
<tr>
<td valign="top" width="250">masterdata.CostcenterGroup</td>
<td valign="top" width="406">the hierarchy structure as shown above</td>
</tr>
<tr>
<td valign="top" width="250">ods.CostcenterGroupExpanded</td>
<td valign="top" width="406">Output table: the expanded tree containing the fields of the table masterdata.Costcenter plus the following additional fields:          </p>
<table border="1" cellspacing="0" cellpadding="2" width="401">
<tbody>
<tr>
<td valign="top" width="111">CostcenterKey</td>
<td valign="top" width="289">the new generated surrogate key</td>
</tr>
<tr>
<td valign="top" width="111">ParentKey</td>
<td valign="top" width="289">the key of the parent node</td>
</tr>
<tr>
<td valign="top" width="111">Level</td>
<td valign="top" width="289">a technical field used during iteration</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>Here is the code:</p>
<p><font face="Courier New">CREATE PROCEDURE [dbo].[ExpandCostcenterGroup]      <br />AS       <br />&#160;&#160;&#160; SET NOCOUNT ON       <br />&#160;&#160;&#160; truncate table ods.costcenterGroupExpanded       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; declare @level int       <br />&#160;&#160;&#160; declare @affectedrows int       <br />&#160;&#160;&#160; declare @totalrowcount int       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; set @level=0       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; insert into ods.costcenterGroupExpanded(costcentergroup,Parentgroup,Description1,Description2,Responsibility,AccountingArea)&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160; Select distinct costcenterGroup, Parent,Description1,Description2,Responsibility,AccountingArea from masterdata.costcentergroup       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; &#8212; Initialize all keys&#160;&#160;&#160; <br />&#160;&#160;&#160; update ods.costcenterGroupExpanded       <br />&#160;&#160;&#160; set ParentKey=(select min(costcenterkey) from ods.costcenterGroupExpanded where costcenterGroup=c.Parentgroup)&#160;&#160;&#160; <br />&#160;&#160;&#160; from ods.costcenterGroupExpanded as c       <br />&#160;&#160;&#160; where not c.ParentGroup is null&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; set @affectedrows=1&#160;&#160;&#160; <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; while @affectedrows&gt;0       <br />&#160;&#160;&#160; begin       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Set @level=@level+1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set @totalrowcount=(select Count(*) from ods.costcenterGroupExpanded)       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert into&#160; ods.costcenterGroupExpanded(costcentergroup,Parentgroup,ParentKey,&quot;level&quot;,Description1,Description2,Responsibility,AccountingArea)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; select distinct cparent.costcentergroup, cparent.Parentgroup,cparent.costcenterKey,@level,cparent.Description1,cparent.Description2,cparent.Responsibility,cparent.AccountingArea       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; from ods.costcenterGroupExpanded as cparent inner join ods.costcenterGroupExpanded as cchild on       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; cparent.Parentgroup=cchild.costcenterGroup       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; where cparent.ParentKey!=cchild.costcenterKey       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; and cchild.&quot;Level&quot;=@level-1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set @affectedrows=@@rowcount       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; end       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; return</font></p>
<p><font face="Courier New">GO</font>     </p>
<p>To keep things simple, I truncate the output table CostcenterGroupExpanded here. However, there is a drawback with this approach: The surrogate keys may change after changes of the imported source tables. This will result in a problem for example for the Excel users. If you’re using filters like ‘show this element only’, only the key is stored.</p>
<p>In order to avoid this you will need to store the mapping and the assigned surrogate key separately. Here it is necessary not only to store the combination of cost center/parent cost center/surrogate key but the whole branch up to the root instead. If you look at the example above you will find two entries of ‘Cost Center 1000’ –&gt; ‘Marketing_DE’, so this is not unique. You have to store the full path up to the root for each node (not only for the leaf-nodes) to make it unique:</p>
<table border="1" cellspacing="0" cellpadding="2" width="525">
<tbody>
<tr>
<td valign="top" width="384"><strong>Path</strong></td>
<td valign="top" width="139"><strong>Given Surrogate Key</strong></td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Internal_HR_DE –&gt; HR_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">1</td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Marketing_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">9</td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Marketing_DE –&gt; Marketing –&gt; Corporate</td>
<td valign="top" width="139">10</td>
</tr>
<tr>
<td valign="top" width="384">Marketing_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">7</td>
</tr>
<tr>
<td valign="top" width="384">Marketing_DE –&gt; Marketing –&gt; Corporate</td>
<td valign="top" width="139">8</td>
</tr>
<tr>
<td valign="top" width="384">…</td>
<td valign="top" width="139">&#160;</td>
</tr>
</tbody>
</table>
<p>In order to store the full path up to the root level I recommend using a hash code (MD5 for example) as this is easier to handle as a long list of node names. In this case our additional key store table would look like this</p>
<table border="1" cellspacing="0" cellpadding="2" width="527">
<tbody>
<tr>
<td valign="top" width="379"><strong>PathMD5</strong></td>
<td valign="top" width="146"><strong>Given Surrogate Key</strong></td>
</tr>
<tr>
<td valign="top" width="379">417913d10ef49f5ff90db9db9f3d2569</td>
<td valign="top" width="146">1</td>
</tr>
<tr>
<td valign="top" width="379">8e27be6b156a52016e01dc049bc39126</td>
<td valign="top" width="146">9</td>
</tr>
<tr>
<td valign="top" width="379">52b1bcaec016e09d4086f37e63814aa5</td>
<td valign="top" width="146">10</td>
</tr>
<tr>
<td valign="top" width="379">…</td>
<td valign="top" width="146">&#160;</td>
</tr>
</tbody>
</table>
<p>The sample code above does not manage this key store table so the keys may change a lot on each load. But for practical purposes you will have to add this key management to make sure the same node always gets the same key.</p>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F07%2Fparallel-hierarchies-in-a-parent-child-structure%2F&amp;linkname=Parallel%20hierarchies%20in%20a%20parent-child%20structure"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server 2005 | SQL Server 2008 | SQL Server 2008R2</p>
<p>This post is about a problem I faced some years ago. The source system was SAP with user defined hierarchies, in this case within the cost center and cost type tables. Parallel hierarchies are well supported in SQL Server BI but in this case, users in SAP could define multiple hierarchies on their own and they wanted these hierarchies to be also available in the OLAP cube. For example, costs associated with the cost center 1000 should be analyzed as shown below:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy" border="0" alt="hierarchy" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy_thumb.png" width="344" height="224" /></a></p>
<p>All costs that are booked on cost center 1000 have to appear in the hierarchy as shown in the sketch. And end-users may also be able to create new hierarchies (for example to analyze a certain project). Of course there may be better ways to model this but in this case we had basically two tables for the cost centers:</p>
<ul>
<li>table CC (Cost Center) </li>
<li>table CCG (Cost Center Group) </li>
</ul>
<p>Table CC contains all cost centers (for example the above cost center 1000) together with additional information (like name, responsible person etc.) while table CCG contains the hierarchy. in CCG we basically find two columns:</p>
<ul>
<li>Node name </li>
<li>Parent node name </li>
</ul>
<table border="1" cellspacing="0" cellpadding="2" width="340">
<tbody>
<tr>
<td valign="top" width="171"><strong>Node</strong></td>
<td valign="top" width="167"><strong>Parent Node</strong></td>
</tr>
<tr>
<td valign="top" width="171">1000</td>
<td valign="top" width="167">Internal_HR_DE</td>
</tr>
<tr>
<td valign="top" width="171">Internal_HR_DE</td>
<td valign="top" width="167">HR_DE</td>
</tr>
<tr>
<td valign="top" width="171">HR_DE</td>
<td valign="top" width="167">Germany</td>
</tr>
<tr>
<td valign="top" width="171">1000</td>
<td valign="top" width="167">Marketing_DE</td>
</tr>
<tr>
<td valign="top" width="171">Marketing_DE</td>
<td valign="top" width="167">Germany</td>
</tr>
<tr>
<td valign="top" width="171">Germany</td>
<td valign="top" width="167">Corporate</td>
</tr>
<tr>
<td valign="top" width="171">Marketing_DE</td>
<td valign="top" width="167">Marketing</td>
</tr>
<tr>
<td valign="top" width="171">Marketing</td>
<td valign="top" width="167">Corporate</td>
</tr>
</tbody>
</table>
<p>Facts (in this case actual or planned costs) are associated with the cost center number (for example 1000). Usually, parent-child hierarchies may be used in this case where we have a very dynamic structure and we do not know the number of levels. However, parent-child may only be used if each node has at most one parent. But here we find the cost center 1000 having two parents (Internal HR Costs DE and Marketing_DE). The same situation exists with the Marketing_DE node (having parents Marketing and Germany).</p>
<p>The solution I’m presenting here is to create additional nodes until each node only has one parent. This is possible as each node of a parent-child hierarchy in SSAS has a name and a key property. So, the name will be identical, while the key will be different. In order to show the process, let’s add internal keys to each of the hierarchy elements.</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy1" border="0" alt="hierarchy1" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy1_thumb.png" width="322" height="248" /></a></p>
<p>What we have to do now is to create additional nodes for every node that has more than one parent. Let’s start with the ‘Marketing_DE’ node:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy2" border="0" alt="hierarchy2" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy2_thumb.png" width="402" height="226" /></a></p>
<p>The additional node gets a new (internal) key, in this example the number 8. But there is still a node with multiple parents: the cost center 1000. Let’s also transform this into separate nodes:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy3" border="0" alt="hierarchy3" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy3_thumb.png" width="400" height="217" /></a></p>
<p>After this step, each node has at most one parent and therefore the structure can be modeled as an SSAS parent-child hierarchy.&#160; </p>
<p>But now, we have to think about the fact rows. Without the hierarchy, facts would have been associated to the cost center by using the internal key (surrogate key), so for example 1000 € that are booked on cost center 1000 would appear in the fact table like</p>
<table border="1" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td valign="top" width="125"><strong>DateKey</strong></td>
<td valign="top" width="125"><strong>CostCenterKey</strong></td>
<td valign="top" width="125"><strong>…</strong></td>
<td valign="top" width="125"><strong>Amount</strong></td>
</tr>
<tr>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
</tr>
<tr>
<td valign="top" width="125">20110630</td>
<td valign="top" width="125">1</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">1000</td>
</tr>
<tr>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
<td valign="top" width="125">…</td>
</tr>
</tbody>
</table>
<p>But now, we have to associate this single fact row to three rows in the dimension table (as the cost center 1000 appears three times now). Therefore we have to use a many-to-many approach, so we add another table, a so called bridge table with the following rows:</p>
<table border="1" cellspacing="0" cellpadding="2" width="290">
<tbody>
<tr>
<td valign="top" width="136"><strong>CostCenterKey</strong></td>
<td valign="top" width="152"><strong>CostCenterDimKey</strong></td>
</tr>
<tr>
<td valign="top" width="136">…</td>
<td valign="top" width="152">…</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">1</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">9</td>
</tr>
<tr>
<td valign="top" width="136">1</td>
<td valign="top" width="152">10</td>
</tr>
<tr>
<td valign="top" width="136">…</td>
<td valign="top" width="152">…</td>
</tr>
</tbody>
</table>
<p>For technical reasons, our fact table has to be linked to a dimension (of flat cost centers), which is also used by the bridge table. This is shown in the following image:</p>
<p><a href="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="hierarchy4" border="0" alt="hierarchy4" src="http://blog.oraylis.de/wp-content/uploads/2011/07/hierarchy4_thumb.png" width="486" height="114" /></a></p>
<p>The most difficult part here is to “normalize” the parent-child structure. One way to do this is to use a stored procedure. Here is the code I used. Within this procedure, the following tables are used:</p>
<table border="1" cellspacing="0" cellpadding="2" width="658">
<tbody>
<tr>
<td valign="top" width="250">masterdata.Costcenter</td>
<td valign="top" width="406">the flat table of cost centers (only leaf-level). The key field is the cost center number (for example 1000 for our cost center from above)</td>
</tr>
<tr>
<td valign="top" width="250">masterdata.CostcenterGroup</td>
<td valign="top" width="406">the hierarchy structure as shown above</td>
</tr>
<tr>
<td valign="top" width="250">ods.CostcenterGroupExpanded</td>
<td valign="top" width="406">Output table: the expanded tree containing the fields of the table masterdata.Costcenter plus the following additional fields:          </p>
<table border="1" cellspacing="0" cellpadding="2" width="401">
<tbody>
<tr>
<td valign="top" width="111">CostcenterKey</td>
<td valign="top" width="289">the new generated surrogate key</td>
</tr>
<tr>
<td valign="top" width="111">ParentKey</td>
<td valign="top" width="289">the key of the parent node</td>
</tr>
<tr>
<td valign="top" width="111">Level</td>
<td valign="top" width="289">a technical field used during iteration</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>Here is the code:</p>
<p><font face="Courier New">CREATE PROCEDURE [dbo].[ExpandCostcenterGroup]      <br />AS       <br />&#160;&#160;&#160; SET NOCOUNT ON       <br />&#160;&#160;&#160; truncate table ods.costcenterGroupExpanded       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; declare @level int       <br />&#160;&#160;&#160; declare @affectedrows int       <br />&#160;&#160;&#160; declare @totalrowcount int       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; set @level=0       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; insert into ods.costcenterGroupExpanded(costcentergroup,Parentgroup,Description1,Description2,Responsibility,AccountingArea)&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160; Select distinct costcenterGroup, Parent,Description1,Description2,Responsibility,AccountingArea from masterdata.costcentergroup       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; &#8212; Initialize all keys&#160;&#160;&#160; <br />&#160;&#160;&#160; update ods.costcenterGroupExpanded       <br />&#160;&#160;&#160; set ParentKey=(select min(costcenterkey) from ods.costcenterGroupExpanded where costcenterGroup=c.Parentgroup)&#160;&#160;&#160; <br />&#160;&#160;&#160; from ods.costcenterGroupExpanded as c       <br />&#160;&#160;&#160; where not c.ParentGroup is null&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; set @affectedrows=1&#160;&#160;&#160; <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; while @affectedrows&gt;0       <br />&#160;&#160;&#160; begin       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Set @level=@level+1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set @totalrowcount=(select Count(*) from ods.costcenterGroupExpanded)       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert into&#160; ods.costcenterGroupExpanded(costcentergroup,Parentgroup,ParentKey,&quot;level&quot;,Description1,Description2,Responsibility,AccountingArea)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; select distinct cparent.costcentergroup, cparent.Parentgroup,cparent.costcenterKey,@level,cparent.Description1,cparent.Description2,cparent.Responsibility,cparent.AccountingArea       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; from ods.costcenterGroupExpanded as cparent inner join ods.costcenterGroupExpanded as cchild on       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; cparent.Parentgroup=cchild.costcenterGroup       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; where cparent.ParentKey!=cchild.costcenterKey       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; and cchild.&quot;Level&quot;=@level-1       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set @affectedrows=@@rowcount       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; end       <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; return</font></p>
<p><font face="Courier New">GO</font>     </p>
<p>To keep things simple, I truncate the output table CostcenterGroupExpanded here. However, there is a drawback with this approach: The surrogate keys may change after changes of the imported source tables. This will result in a problem for example for the Excel users. If you’re using filters like ‘show this element only’, only the key is stored.</p>
<p>In order to avoid this you will need to store the mapping and the assigned surrogate key separately. Here it is necessary not only to store the combination of cost center/parent cost center/surrogate key but the whole branch up to the root instead. If you look at the example above you will find two entries of ‘Cost Center 1000’ –&gt; ‘Marketing_DE’, so this is not unique. You have to store the full path up to the root for each node (not only for the leaf-nodes) to make it unique:</p>
<table border="1" cellspacing="0" cellpadding="2" width="525">
<tbody>
<tr>
<td valign="top" width="384"><strong>Path</strong></td>
<td valign="top" width="139"><strong>Given Surrogate Key</strong></td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Internal_HR_DE –&gt; HR_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">1</td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Marketing_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">9</td>
</tr>
<tr>
<td valign="top" width="384">1000 –&gt; Marketing_DE –&gt; Marketing –&gt; Corporate</td>
<td valign="top" width="139">10</td>
</tr>
<tr>
<td valign="top" width="384">Marketing_DE –&gt; Germany –&gt; Corporate</td>
<td valign="top" width="139">7</td>
</tr>
<tr>
<td valign="top" width="384">Marketing_DE –&gt; Marketing –&gt; Corporate</td>
<td valign="top" width="139">8</td>
</tr>
<tr>
<td valign="top" width="384">…</td>
<td valign="top" width="139">&#160;</td>
</tr>
</tbody>
</table>
<p>In order to store the full path up to the root level I recommend using a hash code (MD5 for example) as this is easier to handle as a long list of node names. In this case our additional key store table would look like this</p>
<table border="1" cellspacing="0" cellpadding="2" width="527">
<tbody>
<tr>
<td valign="top" width="379"><strong>PathMD5</strong></td>
<td valign="top" width="146"><strong>Given Surrogate Key</strong></td>
</tr>
<tr>
<td valign="top" width="379">417913d10ef49f5ff90db9db9f3d2569</td>
<td valign="top" width="146">1</td>
</tr>
<tr>
<td valign="top" width="379">8e27be6b156a52016e01dc049bc39126</td>
<td valign="top" width="146">9</td>
</tr>
<tr>
<td valign="top" width="379">52b1bcaec016e09d4086f37e63814aa5</td>
<td valign="top" width="146">10</td>
</tr>
<tr>
<td valign="top" width="379">…</td>
<td valign="top" width="146">&#160;</td>
</tr>
</tbody>
</table>
<p>The sample code above does not manage this key store table so the keys may change a lot on each load. But for practical purposes you will have to add this key management to make sure the same node always gets the same key.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/07/parallel-hierarchies-in-a-parent-child-structure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Servicepack 1 f&#252;r MS SQL2008 R2</title>
		<link>http://blog.oraylis.de/2011/07/servicepack-1-fr-ms-sql2008-r2/</link>
		<comments>http://blog.oraylis.de/2011/07/servicepack-1-fr-ms-sql2008-r2/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 06:38:44 +0000</pubDate>
		<dc:creator>Daniel Snellen</dc:creator>
				<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[MS SSRS]]></category>
		<category><![CDATA[Technologie]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2011/07/servicepack-1-fr-ms-sql2008-r2/</guid>
		<description><![CDATA[<p>Das Servicepack 1 für den SQL Server 2008 R2 steht bei Microsoft zum Download bereit.    <br /><a title="http://www.microsoft.com/download/en/details.aspx?id=26727" href="http://www.microsoft.com/download/en/details.aspx?id=26727">http://www.microsoft.com/download/en/details.aspx?id=26727</a></p>
<p>Das Servicepack hat die Versionsnummer 10.50.2500.0.    </p>
<p>Zu den Neuerungen gehören:</p>
<ul>
<li>Dynamic Management Views for increased supportability </li>
<li>ForceSeek for improved querying performance </li>
<li>Data-tier Application Component Framework (DAC Fx) for improved database upgrade </li>
<li>Disk space control for PowerPivot </li>
</ul>
<p>Weitere Info befinden sich auf der Download Seite von Microsoft.</p>
<div style="display:block"><small><em>by Daniel Snellen <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F07%2Fservicepack-1-fr-ms-sql2008-r2%2F&amp;linkname=Servicepack%201%20f%26uuml%3Br%20MS%20SQL2008%20R2"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Das Servicepack 1 für den SQL Server 2008 R2 steht bei Microsoft zum Download bereit.    <br /><a title="http://www.microsoft.com/download/en/details.aspx?id=26727" href="http://www.microsoft.com/download/en/details.aspx?id=26727">http://www.microsoft.com/download/en/details.aspx?id=26727</a></p>
<p>Das Servicepack hat die Versionsnummer 10.50.2500.0.    </p>
<p>Zu den Neuerungen gehören:</p>
<ul>
<li>Dynamic Management Views for increased supportability </li>
<li>ForceSeek for improved querying performance </li>
<li>Data-tier Application Component Framework (DAC Fx) for improved database upgrade </li>
<li>Disk space control for PowerPivot </li>
</ul>
<p>Weitere Info befinden sich auf der Download Seite von Microsoft.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/07/servicepack-1-fr-ms-sql2008-r2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSIS Goodie #1: Excel + SSIS + 64 bit = DTS_E_OLEDB_EXCEL_NOT_SUPPORTED ?</title>
		<link>http://blog.oraylis.de/2011/05/ssis-goodie-1-excel-ssis-64-bit-dts_e_oledb_excel_not_supported/</link>
		<comments>http://blog.oraylis.de/2011/05/ssis-goodie-1-excel-ssis-64-bit-dts_e_oledb_excel_not_supported/#comments</comments>
		<pubDate>Mon, 02 May 2011 16:06:50 +0000</pubDate>
		<dc:creator>Daniel Esser</dc:creator>
				<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[64Bit]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[OLEDB]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=1024</guid>
		<description><![CDATA[<p style="text-align: justify">The current majority opinion is that the current Office OLEDB provider (Microsoft.ACE.OLEDB.12.0) and 64-Bit environment can&#8217;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.</p>
<p><span id="more-1024"></span>Some facts about the Office OLEDB provider and SSIS:</p>
<p><strong>Currently the Office OLEDB provider is 32 bit only!</strong></p>
<p style="text-align: justify">That is wrong! Microsoft provides a 64 bit version since December 2010. You can download it here: <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c06b8369-60dd-4b64-a44b-84b371ede16d&amp;displaylang=en">Microsoft Access Database Engine 2010 Redistributable</a></p>
<p><strong>Developing SSIS packages with the 64 bit Version of the provider does not work!</strong></p>
<p style="text-align: justify">Unfortunately Microsoft provides Visual Studio as 32 bit application only (<a href="http://blogs.msdn.com/b/ricom/archive/2009/06/10/visual-studio-why-is-there-no-64-bit-version.aspx">Why?</a>). Therefore it can&#8217;t access/use 64 bit OLEDB providers. As a consequence of that fact you cannot select the Office OLEDB provider. In an development environment you have to use the 32 bit provider.</p>
<p><strong>Excuting SSIS packages in an 64 bit environment with 64 bit OLE DB driver does not work!</strong></p>
<p style="text-align: justify">Yes and no! Using the original Excel-Source does not work. It seems that Microsoft implemented an hard if-statement which throws an exception (DTS_E_OLEDB_EXCEL_NOT_SUPPORTED:  The Excel Connection  Manager is not supported in the 64-bit version of  SSIS, as no OLE DB  provider is available.) if these conditions are met:</p>
<ul>
<li>DTS-Engine runs in 64 bit environment</li>
<li>Connection string is &#8220;Microsoft.ACE.OLEDB.12.0&#8243;</li>
</ul>
<p style="text-align: justify">One solution for that is to use the standard OLEDB Source. Select Microsoft.ACE.OLEDB.12.0 as OLEDB provider and set the <em>extended properties</em> to &#8220;Excel 14.0;HDR=YES&#8221;. Now you can use the normal OLEDB source to retrieve data from an Excel file. I found no restrictions so far.</p>
<p><strong>Excel has to be installed where the SSIS package is to be executed!</strong></p>
<p style="text-align: justify">That is wrong. You only need the <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c06b8369-60dd-4b64-a44b-84b371ede16d&amp;displaylang=en">Microsoft Access Database Engine 2010 Redistributable</a></p>
<p>The lesson is clear: Using Office OLEDB in a 64 bit environment with SSIS works (At least at the command line with DTEXEC)!</p>
<p><a href="http://www.twitter.com/LinkTechie"><img src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png" alt="Follow LinkTechie on Twitter" /></a></p>
<div style="display:block"><small><em>by Daniel Esser <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F05%2Fssis-goodie-1-excel-ssis-64-bit-dts_e_oledb_excel_not_supported%2F&amp;linkname=SSIS%20Goodie%20%231%3A%20Excel%20%2B%20SSIS%20%2B%2064%20bit%20%3D%20DTS_E_OLEDB_EXCEL_NOT_SUPPORTED%20%3F"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify">The current majority opinion is that the current Office OLEDB provider (Microsoft.ACE.OLEDB.12.0) and 64-Bit environment can&#8217;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.</p>
<p><span id="more-1024"></span>Some facts about the Office OLEDB provider and SSIS:</p>
<p><strong>Currently the Office OLEDB provider is 32 bit only!</strong></p>
<p style="text-align: justify">That is wrong! Microsoft provides a 64 bit version since December 2010. You can download it here: <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c06b8369-60dd-4b64-a44b-84b371ede16d&amp;displaylang=en">Microsoft Access Database Engine 2010 Redistributable</a></p>
<p><strong>Developing SSIS packages with the 64 bit Version of the provider does not work!</strong></p>
<p style="text-align: justify">Unfortunately Microsoft provides Visual Studio as 32 bit application only (<a href="http://blogs.msdn.com/b/ricom/archive/2009/06/10/visual-studio-why-is-there-no-64-bit-version.aspx">Why?</a>). Therefore it can&#8217;t access/use 64 bit OLEDB providers. As a consequence of that fact you cannot select the Office OLEDB provider. In an development environment you have to use the 32 bit provider.</p>
<p><strong>Excuting SSIS packages in an 64 bit environment with 64 bit OLE DB driver does not work!</strong></p>
<p style="text-align: justify">Yes and no! Using the original Excel-Source does not work. It seems that Microsoft implemented an hard if-statement which throws an exception (DTS_E_OLEDB_EXCEL_NOT_SUPPORTED:  The Excel Connection  Manager is not supported in the 64-bit version of  SSIS, as no OLE DB  provider is available.) if these conditions are met:</p>
<ul>
<li>DTS-Engine runs in 64 bit environment</li>
<li>Connection string is &#8220;Microsoft.ACE.OLEDB.12.0&#8243;</li>
</ul>
<p style="text-align: justify">One solution for that is to use the standard OLEDB Source. Select Microsoft.ACE.OLEDB.12.0 as OLEDB provider and set the <em>extended properties</em> to &#8220;Excel 14.0;HDR=YES&#8221;. Now you can use the normal OLEDB source to retrieve data from an Excel file. I found no restrictions so far.</p>
<p><strong>Excel has to be installed where the SSIS package is to be executed!</strong></p>
<p style="text-align: justify">That is wrong. You only need the <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=c06b8369-60dd-4b64-a44b-84b371ede16d&amp;displaylang=en">Microsoft Access Database Engine 2010 Redistributable</a></p>
<p>The lesson is clear: Using Office OLEDB in a 64 bit environment with SSIS works (At least at the command line with DTEXEC)!</p>
<p><a href="http://www.twitter.com/LinkTechie"><img src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png" alt="Follow LinkTechie on Twitter" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/05/ssis-goodie-1-excel-ssis-64-bit-dts_e_oledb_excel_not_supported/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>BIDS Goodie #1: How to use macros with SSIS</title>
		<link>http://blog.oraylis.de/2011/02/bids-goodie-1-how-to-use-macros-with-ssis/</link>
		<comments>http://blog.oraylis.de/2011/02/bids-goodie-1-how-to-use-macros-with-ssis/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 13:41:06 +0000</pubDate>
		<dc:creator>Daniel Esser</dc:creator>
				<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[BIDS]]></category>
		<category><![CDATA[Goodie]]></category>
		<category><![CDATA[Macro]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=973</guid>
		<description><![CDATA[<p>Do you ever used macros in Visual Studio? You can do also in BIDS and SSIS&#8230;</p>
<p><span id="more-973"></span>There are many recurring tasks via ETL development. I will now explain how to write a macro to automate these recurring tasks. For example we want to add a frequently used connection manager. Unfortunately the Visual Studio Macros environment isn&#8217;t set up correctly for this.</p>
<p>Go to the Microsoft SQL Server SDK folder: C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies</p>
<p>Copy the following assemblies: Microsoft.SqlServer.DTSPipelineWrap.dll Microsoft.SQLServer.DTSRuntimeWrap.dll</p>
<p>To the Visual Studio Public Assemblies folder: C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies</p>
<p>Now start <em>Visual Studio</em> and open an SSIS project. Select <strong>Other Windows</strong> and then <strong>Macro Explorer</strong> (<em>Alt+F8</em>). Right click on <strong>Macros </strong>in the <strong>Macro Explorer</strong> and select <strong>New Macro Project </strong>called <strong>MySSISMacros</strong>. Create a new module called <strong>Samples</strong>. Double click <strong>Samples </strong>to open the <em>Macro Editor</em>.</p>
<p style="padding-left: 30px;text-align: center"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/MacroExplorer.png"><img class="aligncenter size-full wp-image-980" style="border: 1px solid black" src="http://blog.oraylis.de/wp-content/uploads/2011/02/MacroExplorer.png" alt="" width="295" height="141" /></a></p>
<p style="padding-left: 30px;text-align: left">In the <em>Macro Editor</em> right click at the <strong>MySSISMacros</strong> project and select <strong>Add reference</strong>. Add references to the assemblies above and click <strong>OK</strong>.</p>
<p style="padding-left: 30px;text-align: left"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/AddReferenceMacroExplorer.png"><img class="aligncenter size-full wp-image-986" src="http://blog.oraylis.de/wp-content/uploads/2011/02/AddReferenceMacroExplorer.png" alt="" width="580" height="266" /></a></p>
<p style="text-align: left">Now you are ready to write macros for SSIS development. Here is a very simple example:<span style="color: #3366ff"> </span></p>
<pre style="text-align: left;padding-left: 30px"><span style="color: #3366ff">Imports </span>System
<span style="color: #3366ff">Imports </span>EnvDTE
<span style="color: #3366ff">Imports </span>EnvDTE80
<span style="color: #3366ff">Imports </span>EnvDTE90
<span style="color: #3366ff">Imports </span>EnvDTE90a
<span style="color: #3366ff">Imports </span>System.Diagnostics
<span style="color: #3366ff">Imports </span>Microsoft.SqlServer.Dts.Runtime</pre>
<pre style="text-align: left;padding-left: 30px"><span style="color: #3366ff">Public </span>Module Samples

<span style="color: #3366ff">    Public Sub</span> Example01()
        <span style="color: #3366ff">Dim </span>app <span style="color: #3366ff">As </span><span style="color: #3366ff">New </span>Microsoft.SqlServer.Dts.Runtime.Application()
        <span style="color: #3366ff">Dim </span>filename <span style="color: #3366ff">As </span>String

        filename = DTE.ActiveDocument.FullName()
        <span style="color: #3366ff">Dim </span>p As Package

        <span style="color: #339966">'' Save the document before making changes</span>
        DTE.ActiveDocument.Save()

        <span style="color: #339966">'' Open the package</span>
        p = app.LoadPackage(filename, <span style="color: #3366ff">Nothing</span>)

        <span style="color: #339966">'' Do some changes</span>
        <span style="color: #0000ff">Dim </span>cm As ConnectionManager
        <span style="color: #0000ff">Dim </span>connString, dataSource, catalog, provider, appName <span style="color: #0000ff">As </span>String

        dataSource = <span style="color: #993300">"."</span>
        catalog = <span style="color: #993300">"AdventureWorksDW2008"</span>
        provider = <span style="color: #993300">"SQLNCLI10.1"</span>
        appName = p.Name
        connString = String.Format(<span style="color: #993300">"Data Source={0};Initial Catalog={1};Provider={2};
             Integrated Security=SSPI;Application Name={3};Auto Translate=False;"</span>
             , dataSource, catalog, provider, appName)

        cm = p.Connections.Add(<span style="color: #993300">"OLEDB"</span>)
        cm.ConnectionString = connString
        cm.Description = "AdventureWorks DW"
        cm.Name = "AdventureWorksDW"

        <span style="color: #339966">'' Save the package</span>
        app.SaveToXml(filename, p, <span style="color: #3366ff">Nothing</span>)
<span style="color: #3366ff">    End Sub
End Module

</span></pre>
<p>Download: <span style="color: #3366ff"> </span><span style="color: #3366ff"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/Samples.zip">Samples.zip</a></span></p>
<p><span style="color: #3366ff"> </span></p>
<p>Now open a package and execute the macro. It will add a connection to the active package.</p>
<p style="text-align: left">
<div style="width: 1px;height: 1px;overflow: hidden">Public Module Samples</p>
<p>Public Sub Example01()<br />
Dim a As New Microsoft.SqlServer.Dts.Runtime.Application()<br />
Dim filename As String</p>
<p>filename = DTE.ActiveDocument.FullName()<br />
Dim p As Package</p>
<p>&#8221; Save the document before making changes<br />
DTE.ActiveDocument.Save()</p>
<p>&#8221; Open the package<br />
p = a.LoadPackage(filename, Nothing)</p>
<p>&#8221; Do some changes<br />
p.CreatorName = &#8220;test&#8221;</p>
<p>&#8221; Save the package<br />
a.SaveToXml(filename, p, Nothing)</p>
<p>End Sub<br />
End Module</p>
</div>
<div style="display:block"><small><em>by Daniel Esser <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2011%2F02%2Fbids-goodie-1-how-to-use-macros-with-ssis%2F&amp;linkname=BIDS%20Goodie%20%231%3A%20How%20to%20use%20macros%20with%20SSIS"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Do you ever used macros in Visual Studio? You can do also in BIDS and SSIS&#8230;</p>
<p><span id="more-973"></span>There are many recurring tasks via ETL development. I will now explain how to write a macro to automate these recurring tasks. For example we want to add a frequently used connection manager. Unfortunately the Visual Studio Macros environment isn&#8217;t set up correctly for this.</p>
<p>Go to the Microsoft SQL Server SDK folder: C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies</p>
<p>Copy the following assemblies: Microsoft.SqlServer.DTSPipelineWrap.dll Microsoft.SQLServer.DTSRuntimeWrap.dll</p>
<p>To the Visual Studio Public Assemblies folder: C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies</p>
<p>Now start <em>Visual Studio</em> and open an SSIS project. Select <strong>Other Windows</strong> and then <strong>Macro Explorer</strong> (<em>Alt+F8</em>). Right click on <strong>Macros </strong>in the <strong>Macro Explorer</strong> and select <strong>New Macro Project </strong>called <strong>MySSISMacros</strong>. Create a new module called <strong>Samples</strong>. Double click <strong>Samples </strong>to open the <em>Macro Editor</em>.</p>
<p style="padding-left: 30px;text-align: center"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/MacroExplorer.png"><img class="aligncenter size-full wp-image-980" style="border: 1px solid black" src="http://blog.oraylis.de/wp-content/uploads/2011/02/MacroExplorer.png" alt="" width="295" height="141" /></a></p>
<p style="padding-left: 30px;text-align: left">In the <em>Macro Editor</em> right click at the <strong>MySSISMacros</strong> project and select <strong>Add reference</strong>. Add references to the assemblies above and click <strong>OK</strong>.</p>
<p style="padding-left: 30px;text-align: left"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/AddReferenceMacroExplorer.png"><img class="aligncenter size-full wp-image-986" src="http://blog.oraylis.de/wp-content/uploads/2011/02/AddReferenceMacroExplorer.png" alt="" width="580" height="266" /></a></p>
<p style="text-align: left">Now you are ready to write macros for SSIS development. Here is a very simple example:<span style="color: #3366ff"> </span></p>
<pre style="text-align: left;padding-left: 30px"><span style="color: #3366ff">Imports </span>System
<span style="color: #3366ff">Imports </span>EnvDTE
<span style="color: #3366ff">Imports </span>EnvDTE80
<span style="color: #3366ff">Imports </span>EnvDTE90
<span style="color: #3366ff">Imports </span>EnvDTE90a
<span style="color: #3366ff">Imports </span>System.Diagnostics
<span style="color: #3366ff">Imports </span>Microsoft.SqlServer.Dts.Runtime</pre>
<pre style="text-align: left;padding-left: 30px"><span style="color: #3366ff">Public </span>Module Samples

<span style="color: #3366ff">    Public Sub</span> Example01()
        <span style="color: #3366ff">Dim </span>app <span style="color: #3366ff">As </span><span style="color: #3366ff">New </span>Microsoft.SqlServer.Dts.Runtime.Application()
        <span style="color: #3366ff">Dim </span>filename <span style="color: #3366ff">As </span>String

        filename = DTE.ActiveDocument.FullName()
        <span style="color: #3366ff">Dim </span>p As Package

        <span style="color: #339966">'' Save the document before making changes</span>
        DTE.ActiveDocument.Save()

        <span style="color: #339966">'' Open the package</span>
        p = app.LoadPackage(filename, <span style="color: #3366ff">Nothing</span>)

        <span style="color: #339966">'' Do some changes</span>
        <span style="color: #0000ff">Dim </span>cm As ConnectionManager
        <span style="color: #0000ff">Dim </span>connString, dataSource, catalog, provider, appName <span style="color: #0000ff">As </span>String

        dataSource = <span style="color: #993300">"."</span>
        catalog = <span style="color: #993300">"AdventureWorksDW2008"</span>
        provider = <span style="color: #993300">"SQLNCLI10.1"</span>
        appName = p.Name
        connString = String.Format(<span style="color: #993300">"Data Source={0};Initial Catalog={1};Provider={2};
             Integrated Security=SSPI;Application Name={3};Auto Translate=False;"</span>
             , dataSource, catalog, provider, appName)

        cm = p.Connections.Add(<span style="color: #993300">"OLEDB"</span>)
        cm.ConnectionString = connString
        cm.Description = "AdventureWorks DW"
        cm.Name = "AdventureWorksDW"

        <span style="color: #339966">'' Save the package</span>
        app.SaveToXml(filename, p, <span style="color: #3366ff">Nothing</span>)
<span style="color: #3366ff">    End Sub
End Module

</span></pre>
<p>Download: <span style="color: #3366ff"> </span><span style="color: #3366ff"><a href="http://blog.oraylis.de/wp-content/uploads/2011/02/Samples.zip">Samples.zip</a></span></p>
<p><span style="color: #3366ff"> </span></p>
<p>Now open a package and execute the macro. It will add a connection to the active package.</p>
<p style="text-align: left">
<div style="width: 1px;height: 1px;overflow: hidden">Public Module Samples</p>
<p>Public Sub Example01()<br />
Dim a As New Microsoft.SqlServer.Dts.Runtime.Application()<br />
Dim filename As String</p>
<p>filename = DTE.ActiveDocument.FullName()<br />
Dim p As Package</p>
<p>&#8221; Save the document before making changes<br />
DTE.ActiveDocument.Save()</p>
<p>&#8221; Open the package<br />
p = a.LoadPackage(filename, Nothing)</p>
<p>&#8221; Do some changes<br />
p.CreatorName = &#8220;test&#8221;</p>
<p>&#8221; Save the package<br />
a.SaveToXml(filename, p, Nothing)</p>
<p>End Sub<br />
End Module</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2011/02/bids-goodie-1-how-to-use-macros-with-ssis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BI.Quality 2.0 released on Codeplex</title>
		<link>http://blog.oraylis.de/2010/09/bi-quality-2-0-released-on-codeplex/</link>
		<comments>http://blog.oraylis.de/2010/09/bi-quality-2-0-released-on-codeplex/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 15:28:03 +0000</pubDate>
		<dc:creator>Hilmar Buchta</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[BI.Quality]]></category>
		<category><![CDATA[Test Tools]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2010/09/bi-quality-2-0-released-on-codeplex/</guid>
		<description><![CDATA[<p align="right">SQL Server 2005 | SQL Server 2008 | SQL Server 2008R2</p>
<p>Today we released the new version of <a href="http://biquality.codeplex.com/">BI.Quality on Codeplex</a>. The new release contains many features from the wishlist (check the <a href="http://biquality.codeplex.com/releases/view/44018">release notes</a> for details):</p>
<li>Consistent table interface within one test case e.g. to create tables via local files or query </li>
<li>Unlimited number of queries within one test case </li>
<li>New XmlTableWriter and XmlTableReader to export/import a table </li>
<li>New CsvTableWriter and CsvTableReader to export/import a table </li>
<li>Assert for query execution time </li>
<li>Consistent delta within Asserts, absolute or relative </li>
<li>Extended error handling, e.g. the AssertTable breaks no more after the first failure. </li>
<li>Extended example test suite with all best practice test cases based on Adventure Works DWH 2008 </li>
<li>All changes are fully downwards compatible to Version 1.0.0 </li>
<li>Complete refactoring of the codebase for better extendibility </li>
<li>Improved error messages and self tests
<p>There are only minor changes between 1.9.7 and 2.0.0. Some fixes include the enhanced downwards compatibility for release 1.0 test cases although it is recommended to use the 2.0 syntax for developing new test cases.</p>
</p>
</li>
<div style="display:block"><small><em>by Hilmar Buchta <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2010%2F09%2Fbi-quality-2-0-released-on-codeplex%2F&amp;linkname=BI.Quality%202.0%20released%20on%20Codeplex"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p align="right">SQL Server 2005 | SQL Server 2008 | SQL Server 2008R2</p>
<p>Today we released the new version of <a href="http://biquality.codeplex.com/">BI.Quality on Codeplex</a>. The new release contains many features from the wishlist (check the <a href="http://biquality.codeplex.com/releases/view/44018">release notes</a> for details):</p>
<li>Consistent table interface within one test case e.g. to create tables via local files or query </li>
<li>Unlimited number of queries within one test case </li>
<li>New XmlTableWriter and XmlTableReader to export/import a table </li>
<li>New CsvTableWriter and CsvTableReader to export/import a table </li>
<li>Assert for query execution time </li>
<li>Consistent delta within Asserts, absolute or relative </li>
<li>Extended error handling, e.g. the AssertTable breaks no more after the first failure. </li>
<li>Extended example test suite with all best practice test cases based on Adventure Works DWH 2008 </li>
<li>All changes are fully downwards compatible to Version 1.0.0 </li>
<li>Complete refactoring of the codebase for better extendibility </li>
<li>Improved error messages and self tests
<p>There are only minor changes between 1.9.7 and 2.0.0. Some fixes include the enhanced downwards compatibility for release 1.0 test cases although it is recommended to use the 2.0 syntax for developing new test cases.</p>
</p>
</li>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2010/09/bi-quality-2-0-released-on-codeplex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft&#174; SQL Server&#174; 2008 R2 Best Practices Analyzer verf&#252;gbar</title>
		<link>http://blog.oraylis.de/2010/06/microsoft-sql-server-2008-r2-best-practices-analyzer-verfgbar/</link>
		<comments>http://blog.oraylis.de/2010/06/microsoft-sql-server-2008-r2-best-practices-analyzer-verfgbar/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 18:26:47 +0000</pubDate>
		<dc:creator>Daniel Snellen</dc:creator>
				<category><![CDATA[MS SSAS]]></category>
		<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[MS SSRS]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2008 R2]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/2010/06/microsoft-sql-server-2008-r2-best-practices-analyzer-verfgbar/</guid>
		<description><![CDATA[<p>Seit dem 18.06.2010 steht jetzt auch der SQL Server 2008 R2 Best Practices Analyzer (BPA) zum Download auf der Microsoft Webseite bereit.</p>
<p><a title="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591" href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591">http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591</a></p>
<p>Der SQL Server 2008 R2 BPA ist ein Diagnosetool, welches den SQL Server anhand von Best Practices analysiert und einen Bericht ausgibt, in dem auf mögliche Konfigurationsfehlern oder Fehlenden Updates hinweist.</p>
<p>Der BPA gibt auch genaue Hinweise wie die möglichen Probleme gelöst werden können.</p>
<div style="display:block"><small><em>by Daniel Snellen <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2010%2F06%2Fmicrosoft-sql-server-2008-r2-best-practices-analyzer-verfgbar%2F&amp;linkname=Microsoft%26reg%3B%20SQL%20Server%26reg%3B%202008%20R2%20Best%20Practices%20Analyzer%20verf%26uuml%3Bgbar"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Seit dem 18.06.2010 steht jetzt auch der SQL Server 2008 R2 Best Practices Analyzer (BPA) zum Download auf der Microsoft Webseite bereit.</p>
<p><a title="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591" href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591">http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;FamilyID=0fd439d7-4bff-4df7-a52f-9a1be8725591</a></p>
<p>Der SQL Server 2008 R2 BPA ist ein Diagnosetool, welches den SQL Server anhand von Best Practices analysiert und einen Bericht ausgibt, in dem auf mögliche Konfigurationsfehlern oder Fehlenden Updates hinweist.</p>
<p>Der BPA gibt auch genaue Hinweise wie die möglichen Probleme gelöst werden können.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2010/06/microsoft-sql-server-2008-r2-best-practices-analyzer-verfgbar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Betrieb von SSIS: Anforderungen</title>
		<link>http://blog.oraylis.de/2010/06/betrieb-von-ssis-anforderungen/</link>
		<comments>http://blog.oraylis.de/2010/06/betrieb-von-ssis-anforderungen/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 16:32:00 +0000</pubDate>
		<dc:creator>Thomas Strehlow</dc:creator>
				<category><![CDATA[MS SSIS]]></category>
		<category><![CDATA[Betrieb]]></category>
		<category><![CDATA[Operations]]></category>

		<guid isPermaLink="false">http://blog.oraylis.de/?p=605</guid>
		<description><![CDATA[<p>Nach der Entwicklung von Sql Server Integration Services (SSIS) Projekten, dem ETL Produkt von Microsoft, steht der Betrieb dieser Lösungen an. Wir haben bereits eine Vielzahl von Microsoft basierten BI Projekten realisiert. SSIS spielt dabei stets eine übergeordnete Rolle. In immer mehr Projekten übernehmen wir auch den Betrieb. So individuell die Projekte auch sein mögen, so ähnlich sind die Anforderungen des Betriebs.</p>
<p>Diese Beitragsreihe stellt die allgemeinen Anforderungen für den Betrieb von SSIS dar. In Folgebeiträgen gehe ich auf die Stärken und Schwächen des Produktes ein. Ferner gehe ich darauf ein, wie wir diese Anforderungen standardisiert in unseren Projekten lösen.</p>
<h3>Was sind die allgemeinen Anforderungen?</h3>
<p>Betrieb bedeutet einen Service bereitzustellen, nicht selten 24&#215;7, der zuverlässig funktioniert. Im Falle von SSIS werden periodisch Jobs gestartet, die projektindividuell Daten von A nach B bewegen. Das geschieht in der Regel im verborgenen, d.h. die Prozesse und deren Ergebnisse sind von Hause aus “unsichtbar”. Die nachfolgenden Anforderungen treffen wir in allen Projekten wieder:</p>
<ol>
<li>statusbasierte Ergebnisüberwachung
<ul>
<li>Welche Jobs müssen laufen? </li>
<li>Sind diese erfolgreich gelaufen? Gewünscht ist ein einfacher Soll Ist Vergleich, analog zu Performance Management, zum Beispiel anhand von roten oder grünen Ampeln </li>
</ul>
</li>
<li>Laufzeit basierte Überwachung
<ul>
<li>aktuell aktive Jobs (Wie lange laufen sie schon? Wie lange werden sie vermutlich noch laufen?) </li>
<li>abgeschlossene Jobs (Wie lange läuft der Job gewöhnlich? Wie hat sich die Laufzeit in der letzten Zeit entwickelt? Wie ist der Trend? Wann wird ein kritisches Limit erreicht?) </li>
</ul>
</li>
<li>KPI Überwachung
<ul>
<li>Welche Datenmengen befördert der Job? (aktuell und gewöhnlich) </li>
<li>Anzahl von Fehlern, Korrekturen oder sonstigen wichtigen Ereignissen? </li>
</ul>
</li>
<li>Fehlererkennung und Lösung
<ul>
<li>Sind Fehler aufgetreten? </li>
<li>Wenn ja, wo? Die Praxis zeigt, dass Logging immer falsch ist. Für den Betrieb ist das Logging in der Regel unübersichtlich und überfrachtet. Die wichtigen Informationen müssen wie Rosinen herausgepickt werden. Expertentätigkeit. Für die Fehleranalyse ist es immer zu wenig. Das Optimum ist sehr schwer zu erreichen. </li>
<li>Wer ist der geeignete Ansprechpartner? </li>
<li>Trennung nach technischen Fehlern: In aller Regel auf Systemressourcenengpässe oder Security zurückzuführen, kann durch das BI Team oder die IT gelöst werden. </li>
<li>Und fachliche Fehler: Fehler liegt in aller Regel im Vorsystem (Datenquelle), kann nicht dauerhaft durch das BI Team gelöst werden, sondern fällt in die Zuständigkeit der Quellsysteme. Das ist einer der wesentlichen Beiträge der BI zur Verbesserung der primären Datenqualität! In der Regel wechselt hier die organisatorische Zuständigkeit. Nicht selten wird eine “andere Sprache gesprochen”. </li>
</ul>
</li>
<li>Optimierung
<ul>
<li>Die Daten sind wichtig für die Erkennung des Optimierungsbedarfs. Wie so soft machen 20% des Codes 80% der Laufzeit aus. Deshalb ist eine längerfristige Bevorratung wichtig. </li>
</ul>
</li>
<li>Performance
<ul>
<li>Trotz langer Bevorratung von Logging Informationen müssen alle Berichte innerhalb von 2 Sekunden zur Verfügung stehen </li>
<li>Alle Berichte müssen die Gegenwart zeigen, d.h. Bewirtschaftungszeiten werden nicht akzeptiert&#160; </li>
</ul>
</li>
<li>Nachrüstbarkeit
<ul>
<li>Ganz gleich in welcher Phase ein SSIS Projekt ist: Die hier genannten Anforderungen müssen leicht nachrüstbar sein. Besser noch. Bestehende Loggingdaten sollten in die neue Welt migriert werden können. </li>
</ul>
</li>
</ol>
<h3>BI mit BI betreiben!</h3>
<p>Nach Durchsicht der Anforderungen ist die Lösung recht naheliegend: Alle Betriebsanforderungen erfordern die Sammlung und Aufbereitung von Daten. Das ist die wesentliche BI Kernkompetenz!</p>
<p>Das ist das zentrale Ziel unserer Projekte: Ein standardisiertes Datenmodell mit standardisierten Berichten und einer standardisierten Vorgabe für die Entwicklung, um die hier darstellten Anforderungen zu erfüllen.</p>
<p>Damit erfüllen sich auch weitere, unausgesprochene Anforderungen:</p>
<ol>
<li>Mit der Standardisierung kann eine BI Plattform kostengünstiger erstellt werden. Die Entwickler können sich zu 100% auf die Business Lösung konzentrieren und müssen sich nicht mit Fehlerhandling auseinandersetzen. Wir werden oft in Projekte gerufen, bei denen dieser Teil der Umsetzung eine signifikante Größe eingenommen hat und den Blick auf das wesentliche eintrübt. </li>
<li>Mit der Standardisierung kann eine BI Plattform kostengünstiger betrieben werden. Das Personal benötigt für den 1rst und 2nd Level Support keine tiefen Projektkenntnisse. Es bekommt effizient die Informationen, die es benötigt. </li>
<li>Consultants können zwischen den Projekten leichter wechseln </li>
</ol>
<p><strong>In den nächsten Beiträgen erläutere ich, was die Stärken und Schwächen des Produktes SSIS sind und was zur Erfüllung der Anforderungen erforderlich ist.</strong></p>
<div style="display:block"><small><em>by Thomas Strehlow <ul class="addtoany_list"><li><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.oraylis.de%2F2010%2F06%2Fbetrieb-von-ssis-anforderungen%2F&amp;linkname=Betrieb%20von%20SSIS%3A%20Anforderungen"><img src="http://blog.oraylis.de/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a></li></ul></em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Nach der Entwicklung von Sql Server Integration Services (SSIS) Projekten, dem ETL Produkt von Microsoft, steht der Betrieb dieser Lösungen an. Wir haben bereits eine Vielzahl von Microsoft basierten BI Projekten realisiert. SSIS spielt dabei stets eine übergeordnete Rolle. In immer mehr Projekten übernehmen wir auch den Betrieb. So individuell die Projekte auch sein mögen, so ähnlich sind die Anforderungen des Betriebs.</p>
<p>Diese Beitragsreihe stellt die allgemeinen Anforderungen für den Betrieb von SSIS dar. In Folgebeiträgen gehe ich auf die Stärken und Schwächen des Produktes ein. Ferner gehe ich darauf ein, wie wir diese Anforderungen standardisiert in unseren Projekten lösen.</p>
<h3>Was sind die allgemeinen Anforderungen?</h3>
<p>Betrieb bedeutet einen Service bereitzustellen, nicht selten 24&#215;7, der zuverlässig funktioniert. Im Falle von SSIS werden periodisch Jobs gestartet, die projektindividuell Daten von A nach B bewegen. Das geschieht in der Regel im verborgenen, d.h. die Prozesse und deren Ergebnisse sind von Hause aus “unsichtbar”. Die nachfolgenden Anforderungen treffen wir in allen Projekten wieder:</p>
<ol>
<li>statusbasierte Ergebnisüberwachung
<ul>
<li>Welche Jobs müssen laufen? </li>
<li>Sind diese erfolgreich gelaufen? Gewünscht ist ein einfacher Soll Ist Vergleich, analog zu Performance Management, zum Beispiel anhand von roten oder grünen Ampeln </li>
</ul>
</li>
<li>Laufzeit basierte Überwachung
<ul>
<li>aktuell aktive Jobs (Wie lange laufen sie schon? Wie lange werden sie vermutlich noch laufen?) </li>
<li>abgeschlossene Jobs (Wie lange läuft der Job gewöhnlich? Wie hat sich die Laufzeit in der letzten Zeit entwickelt? Wie ist der Trend? Wann wird ein kritisches Limit erreicht?) </li>
</ul>
</li>
<li>KPI Überwachung
<ul>
<li>Welche Datenmengen befördert der Job? (aktuell und gewöhnlich) </li>
<li>Anzahl von Fehlern, Korrekturen oder sonstigen wichtigen Ereignissen? </li>
</ul>
</li>
<li>Fehlererkennung und Lösung
<ul>
<li>Sind Fehler aufgetreten? </li>
<li>Wenn ja, wo? Die Praxis zeigt, dass Logging immer falsch ist. Für den Betrieb ist das Logging in der Regel unübersichtlich und überfrachtet. Die wichtigen Informationen müssen wie Rosinen herausgepickt werden. Expertentätigkeit. Für die Fehleranalyse ist es immer zu wenig. Das Optimum ist sehr schwer zu erreichen. </li>
<li>Wer ist der geeignete Ansprechpartner? </li>
<li>Trennung nach technischen Fehlern: In aller Regel auf Systemressourcenengpässe oder Security zurückzuführen, kann durch das BI Team oder die IT gelöst werden. </li>
<li>Und fachliche Fehler: Fehler liegt in aller Regel im Vorsystem (Datenquelle), kann nicht dauerhaft durch das BI Team gelöst werden, sondern fällt in die Zuständigkeit der Quellsysteme. Das ist einer der wesentlichen Beiträge der BI zur Verbesserung der primären Datenqualität! In der Regel wechselt hier die organisatorische Zuständigkeit. Nicht selten wird eine “andere Sprache gesprochen”. </li>
</ul>
</li>
<li>Optimierung
<ul>
<li>Die Daten sind wichtig für die Erkennung des Optimierungsbedarfs. Wie so soft machen 20% des Codes 80% der Laufzeit aus. Deshalb ist eine längerfristige Bevorratung wichtig. </li>
</ul>
</li>
<li>Performance
<ul>
<li>Trotz langer Bevorratung von Logging Informationen müssen alle Berichte innerhalb von 2 Sekunden zur Verfügung stehen </li>
<li>Alle Berichte müssen die Gegenwart zeigen, d.h. Bewirtschaftungszeiten werden nicht akzeptiert&#160; </li>
</ul>
</li>
<li>Nachrüstbarkeit
<ul>
<li>Ganz gleich in welcher Phase ein SSIS Projekt ist: Die hier genannten Anforderungen müssen leicht nachrüstbar sein. Besser noch. Bestehende Loggingdaten sollten in die neue Welt migriert werden können. </li>
</ul>
</li>
</ol>
<h3>BI mit BI betreiben!</h3>
<p>Nach Durchsicht der Anforderungen ist die Lösung recht naheliegend: Alle Betriebsanforderungen erfordern die Sammlung und Aufbereitung von Daten. Das ist die wesentliche BI Kernkompetenz!</p>
<p>Das ist das zentrale Ziel unserer Projekte: Ein standardisiertes Datenmodell mit standardisierten Berichten und einer standardisierten Vorgabe für die Entwicklung, um die hier darstellten Anforderungen zu erfüllen.</p>
<p>Damit erfüllen sich auch weitere, unausgesprochene Anforderungen:</p>
<ol>
<li>Mit der Standardisierung kann eine BI Plattform kostengünstiger erstellt werden. Die Entwickler können sich zu 100% auf die Business Lösung konzentrieren und müssen sich nicht mit Fehlerhandling auseinandersetzen. Wir werden oft in Projekte gerufen, bei denen dieser Teil der Umsetzung eine signifikante Größe eingenommen hat und den Blick auf das wesentliche eintrübt. </li>
<li>Mit der Standardisierung kann eine BI Plattform kostengünstiger betrieben werden. Das Personal benötigt für den 1rst und 2nd Level Support keine tiefen Projektkenntnisse. Es bekommt effizient die Informationen, die es benötigt. </li>
<li>Consultants können zwischen den Projekten leichter wechseln </li>
</ol>
<p><strong>In den nächsten Beiträgen erläutere ich, was die Stärken und Schwächen des Produktes SSIS sind und was zur Erfüllung der Anforderungen erforderlich ist.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oraylis.de/2010/06/betrieb-von-ssis-anforderungen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

