<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Practical Business Intelligence</title>
	<atom:link href="http://duncansutcliffe.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://duncansutcliffe.wordpress.com</link>
	<description>Or, How I Solved My Data Warehousing Problems Using SQL Server</description>
	<lastBuildDate>Wed, 22 May 2013 13:24:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='duncansutcliffe.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Practical Business Intelligence</title>
		<link>http://duncansutcliffe.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://duncansutcliffe.wordpress.com/osd.xml" title="Practical Business Intelligence" />
	<atom:link rel='hub' href='http://duncansutcliffe.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Configuring Constrained Delegation in SharePoint 2010</title>
		<link>http://duncansutcliffe.wordpress.com/2011/05/23/configuring-constrained-delegation-in-sharepoint-2010/</link>
		<comments>http://duncansutcliffe.wordpress.com/2011/05/23/configuring-constrained-delegation-in-sharepoint-2010/#comments</comments>
		<pubDate>Mon, 23 May 2011 13:58:19 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Kerberos]]></category>
		<category><![CDATA[SharePoint]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2011/05/23/configuring-constrained-delegation-in-sharepoint-2010/</guid>
		<description><![CDATA[I’ve been doing a *lot* of environment build and configuration work recently, specifically focusing on authentication and the right way to configure Kerberos so that all the business intelligence components of a SharePoint deployment can pass user credentials between themselves and down to data sources.&#160; One of the key things for SharePoint 2010 is that &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2011/05/23/configuring-constrained-delegation-in-sharepoint-2010/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=205&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I’ve been doing a *lot* of environment build and configuration work recently, specifically focusing on authentication and the right way to configure Kerberos so that all the business intelligence components of a SharePoint deployment can pass user credentials between themselves and down to data sources.&#160; One of the key things for SharePoint 2010 is that you will need to configure constrained delegation, whereas in earlier versions you could get away with unconstrained delegation.</p>
<p>There will be a proper series of posts about Kerberos coming along (it’s a big subject with a lot of words to write – I teach a two day course if you are really interested), but in the interim here’s a pictorial guide to the delegation you will need to set up.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/05/constrained-delegation-pathways-map.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="Constrained Delegation Pathways Map" border="0" alt="Constrained Delegation Pathways Map" src="http://duncansutcliffe.files.wordpress.com/2011/05/constrained-delegation-pathways-map_thumb.png?w=644&#038;h=362" width="644" height="362" /></a></p>
<p>The key points are:</p>
<ul>
<li>Web site account delegates to itself, to any other web site accounts and to SSRS account over HTTP</li>
<li>SSRS account delegates to all report data sources’ accounts over MSOLAPSvc.3 and MSSQLSvc</li>
<li>Claims to Windows Token service account delegates to all PerformancePoint, Excel, Visio and InfoPath services data sources’ accounts over MSOLAPSvc.3 and MSSQLSvc</li>
<li>PerformancePoint, Excel, Visio and InfoPath services all delegate to all their required data sources’ accounts over MSOLAPSvc.3 and MSSQLSvc</li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/205/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=205&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2011/05/23/configuring-constrained-delegation-in-sharepoint-2010/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/05/constrained-delegation-pathways-map_thumb.png" medium="image">
			<media:title type="html">Constrained Delegation Pathways Map</media:title>
		</media:content>
	</item>
		<item>
		<title>Listing all the SPNs for a service</title>
		<link>http://duncansutcliffe.wordpress.com/2011/04/15/listing-all-the-spns-for-a-service/</link>
		<comments>http://duncansutcliffe.wordpress.com/2011/04/15/listing-all-the-spns-for-a-service/#comments</comments>
		<pubDate>Fri, 15 Apr 2011 06:26:38 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Kerberos]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2011/04/15/listing-all-the-spns-for-a-service/</guid>
		<description><![CDATA[This came up as a request on the Twitter hashtag #sqlhelp yesterday: how can you list all the SPNs for all the SQL Server instances in a domain? This is pretty easy to achieve using setspn.exe: setspn -T (forest) -F -Q (service)/(server) Both the service and the SPN can use wildcards so the following command &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2011/04/15/listing-all-the-spns-for-a-service/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=201&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This came up as a request on the Twitter hashtag #sqlhelp yesterday: how can you list all the SPNs for all the SQL Server instances in a domain?  This is pretty easy to achieve using setspn.exe:</p>
<p>setspn -T (forest) -F -Q (service)/(server)</p>
<p>Both the service and the SPN can use wildcards so the following command will give a list of all the SQL Server SPNs in the entire forest &#8220;my forest&#8221;.</p>
<p>setspn -T myforest -F -Q MSSQLSvc/*</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/201/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=201&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2011/04/15/listing-all-the-spns-for-a-service/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>
	</item>
		<item>
		<title>Hiding Subreports from the List of Available Report Documents in SharePoint</title>
		<link>http://duncansutcliffe.wordpress.com/2011/01/13/hiding-subreports-from-the-list-of-available-report-documents-in-sharepoint/</link>
		<comments>http://duncansutcliffe.wordpress.com/2011/01/13/hiding-subreports-from-the-list-of-available-report-documents-in-sharepoint/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 09:11:44 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint Integration]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2011/01/13/hiding-subreports-from-the-list-of-available-report-documents-in-sharepoint/</guid>
		<description><![CDATA[Does the SharePoint library which contains your SSRS reports look a bit like this? The user is asked to look at a list of RDL files and guess which one is the top level report, and which are subreports which are only intended to be consumed inside a ‘container’ report or are used as the &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2011/01/13/hiding-subreports-from-the-list-of-available-report-documents-in-sharepoint/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=199&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Does the SharePoint library which contains your SSRS reports look a bit like this?</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-with-reports-and-subreports.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="SharePoint list with reports and subreports" border="0" alt="SharePoint list with reports and subreports" src="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-with-reports-and-subreports_thumb1.png?w=644&#038;h=280" width="644" height="280" /></a></p>
<p>The user is asked to look at a list of RDL files and guess which one is the top level report, and which are subreports which are only intended to be consumed inside a ‘container’ report or are used as the target of hyperlink actions inside another report.&#160; But it’s easy to hide reports which are not intended for users to run individually by making use of SharePoint’s View features.&#160; This example has screenshots from SharePoint 2010 but you can also do the same thing in MOSS 2007.</p>
<p>The goal is not to physically move the subreports, but to make them hidden from the list a user is presented with by categorising them in a managed way.&#160; So, from the Library ribbon, click “Create Column”.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-column-button.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="SharePoint list create column button" border="0" alt="SharePoint list create column button" src="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-column-button_thumb.png?w=311&#038;h=213" width="311" height="213" /></a></p>
<p>In the next dialog, fill in the following values:</p>
<ul>
<li>Column Name: &quot;Report Type&quot; </li>
<li>Type of information: &quot;Choice&quot; </li>
<li>Require that this column contains information: &quot;Yes&quot; </li>
<li>Enforce unique values: &quot;No&quot; </li>
<li>Choices: &quot;Report&quot;, &quot;Subreport&quot; </li>
<li>Display choices using: &quot;Drop-Down Menu&quot; or &quot;Radio Buttons&quot; </li>
<li>Allow &#8216;Fill-in&#8217; choices: &quot;No&quot; </li>
<li>Default value: &quot;Choice&quot;, &quot;Report&quot; </li>
<li>Add to default view: Checked </li>
</ul>
<p>You should end up with a page something like this:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/add-column-to-categorise-as-report-or-subreport.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="Add column to categorise as report or subreport" border="0" alt="Add column to categorise as report or subreport" src="http://duncansutcliffe.files.wordpress.com/2011/01/add-column-to-categorise-as-report-or-subreport_thumb.png?w=465&#038;h=484" width="465" height="484" /></a></p>
<p>After you create the column, you will be returned to the library. As long as you checked the “Add to default view” box when you created the column, you should now have an additional column headed “Report Type”, with no values for any of the reports.&#160; So, edit the properties of each report and set the value for the new “Report Type” property to either “Report” or “Subreport”.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/add-report-type-property-to-the-document-in-the-sharepoint-list.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="Add report type property to the document in the SharePoint list" border="0" alt="Add report type property to the document in the SharePoint list" src="http://duncansutcliffe.files.wordpress.com/2011/01/add-report-type-property-to-the-document-in-the-sharepoint-list_thumb.png?w=720&#038;h=388" width="720" height="388" /></a></p>
<p>Once you have completed categorising your reports and subreports, create a new view by clicking the “Create View” button in the library ribbon.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-view-button.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="SharePoint list create view button" border="0" alt="SharePoint list create view button" src="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-view-button_thumb.png?w=346&#038;h=216" width="346" height="216" /></a></p>
<p>Select “Standard view”, then create the view with the following settings:</p>
<ul>
<li>View name: &quot;Reports only&quot; </li>
<li>Make this the default view: Checked </li>
<li>View audience: &quot;Create a public view&quot; </li>
</ul>
<p>You can add in any additional columns or sorts as you wish, then in the “Filter” section, enter the values you need:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/add-filter-for-reports-only.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="Add filter for reports only" border="0" alt="Add filter for reports only" src="http://duncansutcliffe.files.wordpress.com/2011/01/add-filter-for-reports-only_thumb.png?w=400&#038;h=384" width="400" height="384" /></a></p>
<p>After creating the view, you will be taken back to the report library but now you are only seeing the top level reports.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2011/01/library-with-reports-only-shown.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="Library with reports only shown" border="0" alt="Library with reports only shown" src="http://duncansutcliffe.files.wordpress.com/2011/01/library-with-reports-only-shown_thumb.png?w=824&#038;h=329" width="824" height="329" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/199/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/199/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=199&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2011/01/13/hiding-subreports-from-the-list-of-available-report-documents-in-sharepoint/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-with-reports-and-subreports_thumb1.png" medium="image">
			<media:title type="html">SharePoint list with reports and subreports</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-column-button_thumb.png" medium="image">
			<media:title type="html">SharePoint list create column button</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/add-column-to-categorise-as-report-or-subreport_thumb.png" medium="image">
			<media:title type="html">Add column to categorise as report or subreport</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/add-report-type-property-to-the-document-in-the-sharepoint-list_thumb.png" medium="image">
			<media:title type="html">Add report type property to the document in the SharePoint list</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/sharepoint-list-create-view-button_thumb.png" medium="image">
			<media:title type="html">SharePoint list create view button</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/add-filter-for-reports-only_thumb.png" medium="image">
			<media:title type="html">Add filter for reports only</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2011/01/library-with-reports-only-shown_thumb.png" medium="image">
			<media:title type="html">Library with reports only shown</media:title>
		</media:content>
	</item>
		<item>
		<title>Determining if an Email Address is Valid in SSIS</title>
		<link>http://duncansutcliffe.wordpress.com/2010/12/08/determining-if-an-email-address-is-valid-in-ssis/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/12/08/determining-if-an-email-address-is-valid-in-ssis/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 10:47:04 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2010/12/08/determining-if-an-email-address-is-valid-in-ssis/</guid>
		<description><![CDATA[Had a requirement to establish whether a provided string in a source system matched a valid pattern for email addresses today.&#160; Not to actually try to send a mail to the address, just to check that it was theoretically valid. There is a useful bit of regular expression code available from Microsoft at http://msdn.microsoft.com/en-us/library/01escwtf.aspx so &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/12/08/determining-if-an-email-address-is-valid-in-ssis/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=182&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Had a requirement to establish whether a provided string in a source system matched a valid pattern for email addresses today.&#160; Not to actually try to send a mail to the address, just to check that it was theoretically valid.</p>
<p>There is a useful bit of regular expression code available from Microsoft at <a title="http://msdn.microsoft.com/en-us/library/01escwtf.aspx" href="http://msdn.microsoft.com/en-us/library/01escwtf.aspx">http://msdn.microsoft.com/en-us/library/01escwtf.aspx</a> so all I had to do was work it into a script component.&#160; Here’s how.</p>
<p>Add a script component to the data flow and set the properties you’ll need.&#160; The input column will be the email address field you want to check, then add an output column with the DataType <em>Boolean</em>.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image10.png"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb10.png?w=503&#038;h=294" width="503" height="294" /></a></p>
<p>In the script itself, you need to add the regular expressions library to the script’s <em>using</em> statements:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:f8df8738-642c-4169-9c27-98064e680a5f" class="wlWriterEditableSmartContent">
<pre style="width:709px;height:53px;background-color:White;overflow:auto;"><div><span style="color:#0000FF;">using</span><span style="color:#000000;"> System;
</span><span style="color:#0000FF;">using</span><span style="color:#000000;"> System.Text.RegularExpressions;</span></div></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>Immediately after this, add a new class to actually parse the email address and use the regex to determine its validity:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:8cdd4786-a565-40e4-b7ea-8e8184ec17ec" class="wlWriterEditableSmartContent">
<pre style="width:911px;height:165px;background-color:White;overflow:auto;"><div><span style="color:#0000FF;">public</span><span style="color:#000000;"> </span><span style="color:#0000FF;">class</span><span style="color:#000000;"> RegexUtilities
{
    </span><span style="color:#0000FF;">public</span><span style="color:#000000;"> </span><span style="color:#0000FF;">static</span><span style="color:#000000;"> </span><span style="color:#0000FF;">bool</span><span style="color:#000000;"> IsValidEmail(</span><span style="color:#0000FF;">string</span><span style="color:#000000;"> strIn)
    {
        </span><span style="color:#008000;">//</span><span style="color:#008000;"> Return true if strIn is in valid e-mail format.</span><span style="color:#008000;">
</span><span style="color:#000000;">        </span><span style="color:#0000FF;">return</span><span style="color:#000000;"> Regex.IsMatch(strIn,
               </span><span style="color:#800000;">@&quot;</span><span style="color:#800000;">^(?(&quot;&quot;)(&quot;&quot;.+?&quot;&quot;@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&amp;'\*\+/=\?\^`\{\}\|~\w])*)(?&lt;=[0-9a-zA-Z])@))</span><span style="color:#800000;">&quot;</span><span style="color:#000000;"> </span><span style="color:#000000;">+</span><span style="color:#000000;">
               </span><span style="color:#800000;">@&quot;</span><span style="color:#800000;">(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$</span><span style="color:#800000;">&quot;</span><span style="color:#000000;">);
    }
}</span></div></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>Finally, inside the ProcessInputRow add some code to execute the validation class on each row:</p>
<p><div style="display:inline;float:none;margin:0;padding:0;" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:7a543ca0-cf7d-4a66-99a8-20eb62b61df2" class="wlWriterEditableSmartContent">
<pre style="width:497px;height:255px;background-color:White;overflow:auto;"><div><span style="color:#000000;">    </span><span style="color:#0000FF;">public</span><span style="color:#000000;"> </span><span style="color:#0000FF;">override</span><span style="color:#000000;"> </span><span style="color:#0000FF;">void</span><span style="color:#000000;"> Input0_ProcessInputRow(Input0Buffer Row)
    {
        </span><span style="color:#0000FF;">string</span><span style="color:#000000;"> emailAddress;
        emailAddress </span><span style="color:#000000;">=</span><span style="color:#000000;"> Row.EMAILADDRESS;
                
        </span><span style="color:#0000FF;">bool</span><span style="color:#000000;"> valid </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000FF;">false</span><span style="color:#000000;">;

        </span><span style="color:#0000FF;">if</span><span style="color:#000000;"> (RegexUtilities.IsValidEmail(emailAddress))
            valid </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000FF;">true</span><span style="color:#000000;">;
        </span><span style="color:#0000FF;">else</span><span style="color:#000000;">
            valid </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000FF;">false</span><span style="color:#000000;">;

        Row.ValidEmailAddress </span><span style="color:#000000;">=</span><span style="color:#000000;"> valid;

    }</span></div></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
</p>
<p>&#160;</p>
<p>The field <em>ValidEmailAddress </em>will now be on the dataflow.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/182/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=182&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/12/08/determining-if-an-email-address-is-valid-in-ssis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb10.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Star Schema Modelling Errors&#8211;Dimensions with the Same Cardinality as the Fact Table</title>
		<link>http://duncansutcliffe.wordpress.com/2010/12/07/star-schema-modelling-errorsdimensions-with-the-same-cardinality-as-the-fact-table/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/12/07/star-schema-modelling-errorsdimensions-with-the-same-cardinality-as-the-fact-table/#comments</comments>
		<pubDate>Tue, 07 Dec 2010 12:00:10 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Data Modelling]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2010/12/07/star-schema-modelling-errorsdimensions-with-the-same-cardinality-as-the-fact-table/</guid>
		<description><![CDATA[What’s wrong with this data mart model? The sales fact table has an associated dimension which describes the sale record.&#160; There is a surrogate key relationship between the fact and dimension tables but there’s also the business key (SaleNumber) from the source system. Why is this bad? There will be a one-to-one relationship between the &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/12/07/star-schema-modelling-errorsdimensions-with-the-same-cardinality-as-the-fact-table/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=176&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>What’s wrong with this data mart model?</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image8.png"><img style="background-image:none;padding-left:0;padding-right:0;display:inline;padding-top:0;border-width:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb8.png?w=549&#038;h=324" width="549" height="324" /></a></p>
<p>The sales fact table has an associated dimension which describes the sale record.&#160; There is a surrogate key relationship between the fact and dimension tables but there’s also the business key (SaleNumber) from the source system.</p>
<p>Why is this bad?</p>
<ul>
<li><font color="#656565">There will be a one-to-one relationship between the fact table and the dimension, which means the dimension is potentially going to be huge.&#160; Joining between fact and this dimension will be slow at query time.</font> </li>
<li><font color="#656565">The dimension is very poorly built for Analysis Services.&#160; If Status only has three possible values but those three are being repeated on every line instead of normalised into their own dimension, SSAS build times will be bigger than they should be.</font> </li>
<li><font color="#656565">If you have facts that get updated in the source, you are going to have to manage this in two places in the data warehouse.&#160; A type 2 SCD with millions of rows in it like this one is going to be painfully slow to populate on your ETL runs.</font> </li>
<li><font color="#656565">Some of the attributes should have their own dimensions – status, payment method, order method, carrier – or maybe a junk dimension.&#160; This will compress the dimension to the unique values of each of these fields rather than making it as big as the fact table itself.</font> </li>
<li><font color="#656565">The CarriageWeight field is meaningless as an attribute because no-one would ever want to analyse orders by their carriage weight.&#160; So it should be included on the fact table, though in an SSAS cube its AggregationType would be set to None.</font> </li>
<li><font color="#656565">Delivery address fields could go in several places:</font>
<ul>
<li><font color="#656565">Into a delivery address dimension</font> </li>
<li><font color="#656565">Onto the fact table if they aren’t used for analysis purposes</font> </li>
<li><font color="#656565">Into the customer dimension if each customer only has one delivery address</font> </li>
</ul>
</li>
</ul>
<p>So – dimensions which describe facts in a one-to-one way should be avoided.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/176/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/176/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=176&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/12/07/star-schema-modelling-errorsdimensions-with-the-same-cardinality-as-the-fact-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb8.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Extracting Source Records by Time Window</title>
		<link>http://duncansutcliffe.wordpress.com/2010/12/05/extracting-source-records-by-time-window/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/12/05/extracting-source-records-by-time-window/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 14:32:19 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/?p=172</guid>
		<description><![CDATA[More and more source systems seem to include 24 hour operation – for example retailers who might once have worked nine to five now accept orders via the Internet.&#160; At the same time, data warehouses are getting closer to ‘real time’ information provision by running load procedures more than once per day. So it’s more &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/12/05/extracting-source-records-by-time-window/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=172&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>More and more source systems seem to include 24 hour operation – for example retailers who might once have worked nine to five now accept orders via the Internet.&#160; At the same time, data warehouses are getting closer to ‘real time’ information provision by running load procedures more than once per day.</p>
<p>So it’s more important than ever to make sure you set a defined time period for which your ETL is loading records, with a start and end time.&#160; This period needs to be respected for every extract in a run, so for example you need to make sure you extract order headers and order lines which cover exactly the same time period.</p>
<p>Here’s the simplest but most reliable way I have been able to find to do this.</p>
<p>The first step in the SSIS defines a new load and sets the date/time range which the load covers.&#160; Subsequent steps use these time periods when selecting source records.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="Simplified SSIS package showing setting a time period range with an Execute SQL task" border="0" alt="Simplified SSIS package showing setting a time period range with an Execute SQL task" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb.png?w=463&#038;h=207" width="463" height="207" /></a>(In a “real” solution I’d expect the first step to be done in your ‘master’ package and the results passed to subsequent child packages.)</p>
<p>The Execute SQL step does two things: creates a new load and sets the time window it is working with, then places the information in package variables.&#160; The variables required are a load ID, a start date/time and a finish date/time:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image1.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb1.png?w=319&#038;h=157" width="319" height="157" /></a></p>
<p>In the meta-database which logs and controls the ETL runs, there is a simple table which mirrors these three values.</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:4a00b123-45d5-41d9-8df1-035e425ce2b7" class="wlWriterEditableSmartContent">
<pre style="width:400px;height:131px;background-color:White;overflow:auto;"><div><span style="color:#0000FF;">CREATE</span><span style="color:#000000;"> </span><span style="color:#0000FF;">TABLE</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">dbo</span><span style="color:#FF0000;">]</span><span style="color:#000000;">.</span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">LoadWindowControl</span><span style="color:#FF0000;">]</span><span style="color:#000000;">(
    </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">LoadID</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">int</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#FF00FF;">identity</span><span style="color:#000000;"> </span><span style="color:#808080;">NOT</span><span style="color:#000000;"> </span><span style="color:#0000FF;">NULL</span><span style="color:#000000;">,
    </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">LoadFrom</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">datetime</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#808080;">NOT</span><span style="color:#000000;"> </span><span style="color:#0000FF;">NULL</span><span style="color:#000000;">,
    </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">LoadTo</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">datetime</span><span style="color:#FF0000;">]</span><span style="color:#000000;"> </span><span style="color:#808080;">NOT</span><span style="color:#000000;"> </span><span style="color:#0000FF;">NULL</span><span style="color:#000000;">
) </span><span style="color:#0000FF;">ON</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">PRIMARY</span><span style="color:#FF0000;">]</span><span style="color:#000000;">;
</span><span style="color:#0000FF;">GO</span></div></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>The SQL task calls a stored procedure:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:fefd3684-4f31-4c57-98f1-56d42d2f7330" class="wlWriterEditableSmartContent">
<pre style="width:709px;height:472px;background-color:White;overflow:auto;"><div><span style="color:#0000FF;">CREATE</span><span style="color:#000000;"> </span><span style="color:#0000FF;">PROCEDURE</span><span style="color:#000000;"> </span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">dbo</span><span style="color:#FF0000;">]</span><span style="color:#000000;">.</span><span style="color:#FF0000;">[</span><span style="color:#FF0000;">uspSetLoadWindow</span><span style="color:#FF0000;">]</span><span style="color:#000000;">
    </span><span style="color:#008000;">@LoadID</span><span style="color:#000000;"> </span><span style="color:#0000FF;">int</span><span style="color:#000000;"> output,
    </span><span style="color:#008000;">@LoadFrom</span><span style="color:#000000;"> </span><span style="color:#0000FF;">datetime</span><span style="color:#000000;"> output,
    </span><span style="color:#008000;">@LoadTo</span><span style="color:#000000;"> </span><span style="color:#0000FF;">datetime</span><span style="color:#000000;"> output
</span><span style="color:#0000FF;">AS</span><span style="color:#000000;">
</span><span style="color:#0000FF;">BEGIN</span><span style="color:#000000;">

    </span><span style="color:#0000FF;">SET</span><span style="color:#000000;"> NOCOUNT </span><span style="color:#0000FF;">ON</span><span style="color:#000000;">;

    </span><span style="color:#0000FF;">declare</span><span style="color:#000000;"> </span><span style="color:#008000;">@StartTime</span><span style="color:#000000;"> </span><span style="color:#0000FF;">datetime</span><span style="color:#000000;">;
    </span><span style="color:#0000FF;">select</span><span style="color:#000000;"> </span><span style="color:#008000;">@StartTime</span><span style="color:#000000;"> </span><span style="color:#808080;">=</span><span style="color:#000000;"> </span><span style="color:#FF00FF;">dateadd</span><span style="color:#000000;">(s, </span><span style="color:#800000;font-weight:bold;">1</span><span style="color:#000000;">, </span><span style="color:#FF00FF;">coalesce</span><span style="color:#000000;">(</span><span style="color:#FF00FF;">max</span><span style="color:#000000;">(LoadTo), </span><span style="color:#800000;font-weight:bold;">0</span><span style="color:#000000;">)) </span><span style="color:#0000FF;">from</span><span style="color:#000000;"> LoadWindowControl;
    
    </span><span style="color:#0000FF;">declare</span><span style="color:#000000;"> </span><span style="color:#008000;">@EndTime</span><span style="color:#000000;"> </span><span style="color:#0000FF;">datetime</span><span style="color:#000000;">;
    </span><span style="color:#0000FF;">set</span><span style="color:#000000;"> </span><span style="color:#008000;">@EndTime</span><span style="color:#000000;"> </span><span style="color:#808080;">=</span><span style="color:#000000;"> </span><span style="color:#FF00FF;">convert</span><span style="color:#000000;">(</span><span style="color:#0000FF;">datetime</span><span style="color:#000000;">, </span><span style="color:#FF00FF;">convert</span><span style="color:#000000;">(</span><span style="color:#0000FF;">varchar</span><span style="color:#000000;">(</span><span style="color:#800000;font-weight:bold;">30</span><span style="color:#000000;">), </span><span style="color:#FF00FF;">CURRENT_TIMESTAMP</span><span style="color:#000000;">, </span><span style="color:#800000;font-weight:bold;">120</span><span style="color:#000000;">));
    
    </span><span style="color:#0000FF;">insert</span><span style="color:#000000;"> </span><span style="color:#0000FF;">into</span><span style="color:#000000;"> LoadWindowControl (LoadFrom, LoadTo)
    </span><span style="color:#0000FF;">values</span><span style="color:#000000;"> (</span><span style="color:#008000;">@StartTime</span><span style="color:#000000;">, </span><span style="color:#008000;">@EndTime</span><span style="color:#000000;">)
    
    </span><span style="color:#0000FF;">select</span><span style="color:#000000;"> </span><span style="color:#008000;">@LoadID</span><span style="color:#000000;"> </span><span style="color:#808080;">=</span><span style="color:#000000;"> </span><span style="color:#008000;font-weight:bold;">@@IDENTITY</span><span style="color:#000000;">, </span><span style="color:#008000;">@LoadFrom</span><span style="color:#000000;"> </span><span style="color:#808080;">=</span><span style="color:#000000;"> </span><span style="color:#008000;">@StartTime</span><span style="color:#000000;">, </span><span style="color:#008000;">@LoadTo</span><span style="color:#000000;"> </span><span style="color:#808080;">=</span><span style="color:#000000;"> </span><span style="color:#008000;">@EndTime</span><span style="color:#000000;">
</span><span style="color:#0000FF;">END</span><span style="color:#000000;">;
</span><span style="color:#0000FF;">GO</span></div></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>This is very simple – just adding a new record into the list of loads with an end date of “now” and a start date of the last end plus one second.&#160; All three of these values are passed back as output parameters so the SSIS package can put them into variables.&#160; Calling the proc from SSIS is easy:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image2.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb2.png?w=562&#038;h=484" width="562" height="484" /></a></p>
<p> And the parameter mapping inserts the right value to the right variable:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image3.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb3.png?w=667&#038;h=234" width="667" height="234" /></a></p>
<p>The first time this package runs, the table gets a record like this:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image4.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb4.png?w=378&#038;h=95" width="378" height="95" /></a></p>
<p>To check these values are being passed into the SSIS variables, here’s a quick look at the Locals window for anyone confused by these dates, remember I’m in the UK so the format is dd/mm/yyyy):</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image5.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb5.png?w=351&#038;h=59" width="351" height="59" /></a></p>
<p>With these parameter values now populated them you can use them as part of the SQL command in each source.&#160; For example:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image6.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb6.png?w=507&#038;h=482" width="507" height="482" /></a></p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/12/image7.png"><img style="background-image:none;border-bottom:0;border-left:0;padding-left:0;padding-right:0;display:inline;border-top:0;border-right:0;padding-top:0;" title="image" border="0" alt="image" src="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb7.png?w=314&#038;h=214" width="314" height="214" /></a></p>
<p>For each package you can pass these variables through as configurations, or you could just pass through the load ID and retrieve the related dates using an Execute SQL task.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/172/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/172/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=172&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/12/05/extracting-source-records-by-time-window/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb.png" medium="image">
			<media:title type="html">Simplified SSIS package showing setting a time period range with an Execute SQL task</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb1.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb2.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb3.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb4.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb5.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb6.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/12/image_thumb7.png" medium="image">
			<media:title type="html">image</media:title>
		</media:content>
	</item>
		<item>
		<title>Handling and Tuning Really Large Analysis Services Cubes</title>
		<link>http://duncansutcliffe.wordpress.com/2010/10/15/handling-and-tuning-really-large-analysis-services-cubes/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/10/15/handling-and-tuning-really-large-analysis-services-cubes/#comments</comments>
		<pubDate>Fri, 15 Oct 2010 16:04:52 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Tuning]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2010/10/15/handling-and-tuning-really-large-analysis-services-cubes/</guid>
		<description><![CDATA[Until recently, the largest SSAS cube I had worked with was around 500gb – part of the BI solution at a big retailer.&#160; But recently I built a cube that almost hit the terabyte mark – 911 gigabytes when I first deployed it against real data volumes. Can Analysis Services even deal with this type &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/10/15/handling-and-tuning-really-large-analysis-services-cubes/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=154&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Until recently, the largest SSAS cube I had worked with was around 500gb – part of the BI solution at a big retailer.&#160; But recently I built a cube that almost hit the terabyte mark – 911 gigabytes when I first deployed it against real data volumes.</p>
<p>Can Analysis Services even deal with this type of cube size?&#160; What kind of hardware do you need in order to run it?&#160; How do you tune a cube in the terabyte range? Just how quick can your query response times be?</p>
<p>In this case, the cube contains just under 14 billion (13, 680, 000, 000 to be exact) fact table records.&#160; These can be drilled down to a time level of <em>minute</em>.&#160; The cube users need to be able to drill from year down to minute, and across dimensions of client, fact location and geography.&#160; And we need to be getting ‘instant’ response using PerformancePoint or Excel for free ad hoc analysis.&#160; This all adds up to needing a very highly tuned cube.&#160; It took about three days to reach a point I was beginning to be happy with the performance of the cube.&#160; The only way to approach it was to think of a very large cube as simply a regular cube but with more data in it and follow a standard tuning procedure, then add more if required.</p>
<p>So, the approach is:</p>
<ol>
<li>Sort the dimensions out.&#160; When you have this many fact records, the cube needs dimensions set up as efficiently as possible.</li>
<li>Remove many-to-many structures if possible; optimise them if you really can’t live without them. (This was probably the biggest single optimisation.)</li>
<li>Sort the partitions out. Partition on an attribute (or set) that will often be used in queries at the level you are partitioning. Use the slice property. Don’t use any attribute that’s used in a many-to-many relationship as a partition slice.</li>
<li>Aggregate efficiently and appropriately.</li>
</ol>
<h3>Dimension Optimisation</h3>
<p>I think this is probably the foundation of cube tuning.&#160; All the aggregations in the world won’t really solve your tuning problems if they are having to work with badly built dimensions.</p>
<p>Here are my rules:</p>
<ul>
<li><font color="#656565">Don’t include any attributes that won’t be needed just because they are in the data warehouse dimension.       <br />For example, things like addresses are almost never needed.&#160; By including these you are simply increasing the number of cells your cube has to contain – therefore the query space and the amount of work the engine has to do when loading up the cube from disk.</font></li>
<li><font color="#656565">If there are columns you really must include but will be rarely queried and don’t form part of an attribute hierarchy, turn off <em>Attribute Hierarchy Enabled</em> and make them a property of the key.&#160; They will still be available in Excel or whatever for any users that desperately need them.</font></li>
<li><font color="#656565">Keep every attribute’s key small.&#160; You may need an attribute key which has more than one column – if so use the minimum columns you can.&#160; For example, just because your date hierarchy goes Year –&gt; Quarter –&gt; Month, the key for the month attribute doesn’t need to do the same.&#160; Just Year and Month would do.       <br />For text attributes with lots of different values, seriously consider creating a numeric key column for them in the source dimension.</font></li>
<li><font color="#656565">Design hierarchies properly and set up the attribute relationships correctly. <em>Always</em> put attributes into hierarchies if you possibly can – it might look to the end user that they get the right result by using attributes rather than hierarchies but it is nowhere near as efficient.</font></li>
<li><font color="#656565">If an attribute is used in a hierarchy, hide it as an attribute.&#160; Just to enforce the hierarchies you’ve designed on your users.&#160; Even in a date dimension don’t let the year/quarter/month/week/etc attributes remain visible.&#160; Put them into logical hierarchies and then hide the attribute.&#160; Create ‘Month of Year’ type attributes and make those visible instead – and make sure you have both a numeric key and a text name for these types of attribute.</font></li>
<li><font color="#656565">Make relationships ‘rigid’ if you can (dates will be a good candidate for example), but don’t compromise your ability to perform incremental refreshes just to do this.</font></li>
</ul>
<p>Here’s an extreme example.&#160; When the cube was first put together, there was a dimension that looked like this:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/10/poorlystructureddimension.png"><img style="border-bottom:0;border-left:0;display:inline;border-top:0;border-right:0;" title="Poorly structured dimension" border="0" alt="Poorly structured dimension" src="http://duncansutcliffe.files.wordpress.com/2010/10/poorlystructureddimension_thumb.png?w=339&#038;h=561" width="339" height="561" /></a> </p>
<p>Almost everything there is never going to be used in any type of query.&#160; In fact only one attribute is needed so the dimension should look like this:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/10/optimiseddimension.png"><img style="border-bottom:0;border-left:0;display:inline;border-top:0;border-right:0;" title="Optimised dimension" border="0" alt="Optimised dimension" src="http://duncansutcliffe.files.wordpress.com/2010/10/optimiseddimension_thumb.png?w=278&#038;h=184" width="278" height="184" /></a> </p>
<p>Not only has the majority of attributes been deleted, but the remaining one has a rigid relationship.</p>
<h3>Many to Many Dimensions</h3>
<p>Effectively, a many-to-many is to cube performance what Kryptonite is to Superman. The additional amount of work required each time the many-to-many dimension is queried is considerable, and the amount of aggregations required to improve their performance will explode the size of your cube.&#160; If you really must have a many-to-many, keep the intermediate measure group as small as possible by removing repeating rows (i.e. every row in it should be distinct).</p>
<p>One pitfall – if you use a many-to-many dimension as part of your partitioning strategy, you cannot set the slice property (it always produces an error on processing) of the partition.&#160; Even worse, the engine won’t be able to determine which partitions contain the data it needs for query results (i.e. automatically slice) so every partition in the cube will get touched on every query.&#160; These are probably facets of the same problem.</p>
<p>There’s a white paper on tuning many-to-many dimensions at <a title="http://blogs.msdn.com/b/sqlcat/archive/2007/12/21/new-best-practices-articles-published-analysis-services-many-to-many-dimensions-query-performance-optimization-techniques.aspx" href="http://blogs.msdn.com/b/sqlcat/archive/2007/12/21/new-best-practices-articles-published-analysis-services-many-to-many-dimensions-query-performance-optimization-techniques.aspx">http://blogs.msdn.com/b/sqlcat/archive/2007/12/21/new-best-practices-articles-published-analysis-services-many-to-many-dimensions-query-performance-optimization-techniques.aspx</a>.&#160; But my advice would be – avoid them at all costs on a cube this size because you are going to have so much data to query that their performance penalty is going to be be massive.</p>
<h3>Partition Design</h3>
<p>Every tip I’ve read on the Internet tells you that no partition should have more than twenty million records in it.&#160; But as the screenshot below shows, my cube has eight or nine times that number per partition.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/10/partitioncounts.png"><img style="border-bottom:0;border-left:0;display:inline;border-top:0;border-right:0;" title="Partition Counts" border="0" alt="Partition Counts" src="http://duncansutcliffe.files.wordpress.com/2010/10/partitioncounts_thumb.png?w=491&#038;h=159" width="491" height="159" /></a> </p>
<p>Why not make the partitions smaller? Several reasons:</p>
<ul>
<li><font color="#656565">The measure group is already partitioned by month (a very common query unit), it’s just that each month has a lot of records. Partitioning by the next smallest time unit (day) would mean we’d need approx 30 times as many partitions which would be:</font></li>
<ul>
<li><font color="#656565">Difficult to manage</font></li>
<li><font color="#656565">A lot of individual files for the cube to need to read data from</font></li>
<li><font color="#656565">A problem for aggregation since the largest meaningful aggregate would be one day (remember aggregations are by partition)</font></li>
</ul>
<li><font color="#656565">Partitioning by another attribute isn’t practical because unlike dates, most other attributes would probably have a variable number of members (imagine partitioning by client for example) so you would have to dynamically add and remove partitions.</font></li>
<li><font color="#656565">The cube partition scheme exactly maps to the data warehouse’s fact table partitioning scheme.&#160; So loading a partition has a nice performance boost – the RDMBS just has to supply the entire contents of one database partition for each partition we process in the cube.&#160; We actually have <em>no indexes at all</em> on the fact tables, which certainly speeds up ETL inserts.</font></li>
<li><font color="#656565">Ultimately, the cube performs absolutely perfectly even with these very large partitions.</font></li>
</ul>
<p>With the partitions designed and the queries added, <em>make sure you set the Slice property on every partition</em>.&#160; Ignore the common myth that you do not need to set it on MOLAP partitions – it takes a second to set it, it provides a nice safeguard against errors in your partitioning statements, and it guarantees the engine will hit just the required partitions at query time.</p>
<h3>Aggregations</h3>
<p>On a cube this large, you really will need very good aggregations – aggregations that are specifically designed to support exactly the queries being executed.&#160; This is because there is so much granularity level data that any query which can’t use an aggregation is going to be incredibly slow.&#160; Experience with this terabyte cube showed the best approach was:</p>
<ul>
<li><font color="#656565">Find <strong>one</strong> frequently used attribute and set its aggregation usage to <em>Full</em>. The best candidate here is <em>Month</em> because:</font></li>
<ul>
<li><font color="#656565">That matches the partition strategy</font></li>
<li><font color="#656565">There are a relatively small number of members (only 60 if there are five years’ of data) so the aggregation designer should respect your setting</font></li>
<li><font color="#656565">Month is a good attribute for almost all queries.&#160; You usually query based on a date range (this month, all months in this year, etc.)</font></li>
</ul>
<li><font color="#656565">Every other attribute in every dimension is just left as <em>Default</em>.</font></li>
<li><font color="#656565">Use <a href="http://bidshelper.codeplex.com/" target="_blank">BIDS Helper</a> to update all the counts in the cube. In a cube this size, be prepared to leave it setting counts overnight!</font></li>
<li><font color="#656565">Although the aggregation designer still won’t produce particularly useful aggregations, I ran it anyway on all the measure groups.&#160; Deciding how many aggregations you want it to produce is a tightrope walk – too few and it’s pointless, too many and you can start seeing gigabytes of aggregations being designed.&#160; The rules I followed eventually were:</font></li>
<ul>
<li><font color="#656565">Use the ‘Until I click stop’ setting</font></li>
<li><font color="#656565">Watch the size and number of aggregations being generated.&#160; Aim for under 150 aggregations, or less than three or four gigabytes.</font></li>
</ul>
</ul>
<h5></h5>
<h4>Usage Based Optimisations</h4>
<p>This is the real place you are going to win with aggregations.&#160; Using the designer, or designing your own (unless you really understand what you are doing) is just playing at it.</p>
<p>Once you’ve got your cube built, get query logging enabled straight away.&#160; This is easy:</p>
<ul>
<li><font color="#656565">Create a database to hold the logs</font></li>
<li><font color="#656565">Enable logging in the server’s properties and set the name of the table you will hold the logs in.</font></li>
</ul>
<p>You want to use the logs in a structured way, so make sure you are doing this in development – don’t wait until the cube is in production and you start getting complaints from users about speed.&#160; Users will be running all sorts of random queries which will be getting logged and affecting the optimisation recommendations.&#160; That’s fine but at this stage you want to remain in control of everything that’s affecting your cube’s design.</p>
<p>With an empty query log (hint: it’s a database table so you can always TRUNCATE it to clear it between tuning runs, but SSAS will empty it for you each time you deploy a change to the cube), navigate to your dashboard and open every page in it. Run each of your reports. I.e. do one of every thing that will be a regular activity.&#160; This will enable the optimisation wizard to put together a set of aggregations that support everything you have built.</p>
<p>At this point, I ran the usage based optimisation wizard against each measure group, accepted its suggestions and merged them into the existing aggregation designs.</p>
<p>Over time, of course, this cube would have further aggregations added based on real-world usage by users.</p>
<h3>Results</h3>
<p>How quick is the cube after all this work?&#160; The following video should give an idea:</p>
<div style="display:inline;float:none;margin:0;padding:0;" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:6ad521a8-b607-47e1-b45c-1c1932f7434a" class="wlWriterEditableSmartContent">
<div><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='584' height='359' src='http://www.youtube.com/embed/oa0kzx0ur64?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span></div>
</div>
<p>Promise: no smoke and mirrors, frames cut out, or anything like that.</p>
<p>And the hardware?&#160; This is on a DL680 (4 x quad) with 64gb or memory.&#160; Nothing special.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/154/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/154/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=154&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/10/15/handling-and-tuning-really-large-analysis-services-cubes/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/10/poorlystructureddimension_thumb.png" medium="image">
			<media:title type="html">Poorly structured dimension</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/10/optimiseddimension_thumb.png" medium="image">
			<media:title type="html">Optimised dimension</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/10/partitioncounts_thumb.png" medium="image">
			<media:title type="html">Partition Counts</media:title>
		</media:content>
	</item>
		<item>
		<title>Kerberos in a Clustered and Load Balanced BI Deployment</title>
		<link>http://duncansutcliffe.wordpress.com/2010/09/30/kerberos-in-a-clustered-and-load-balanced-bi-deployment/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/09/30/kerberos-in-a-clustered-and-load-balanced-bi-deployment/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 12:09:44 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Kerberos]]></category>
		<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SharePoint Integration]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[Load Balanced]]></category>
		<category><![CDATA[NLB]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2010/09/30/kerberos-in-a-clustered-and-load-balanced-bi-deployment/</guid>
		<description><![CDATA[As if it weren’t hard enough getting Kerberos delegation to work properly in your average business intelligence distributed architecture, there is another level of knowledge required when you’re building an environment that’s got lots of resilience built in. This post covers the following scenarios: Clustered SQL Server Clustered Analysis Services Scale out and load balanced &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/09/30/kerberos-in-a-clustered-and-load-balanced-bi-deployment/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=144&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>As if it weren’t hard enough getting Kerberos delegation to work properly in your average business intelligence distributed architecture, there is another level of knowledge required when you’re building an environment that’s got lots of resilience built in.</p>
<p>This post covers the following scenarios:</p>
<ul>
<li>Clustered SQL Server</li>
<li>Clustered Analysis Services</li>
<li>Scale out and load balanced Reporting Services</li>
<li>Reporting Services integrated with SharePoint</li>
</ul>
<p>I’ve been building just such an architecture in a lab environment using SQL Server 2008R2 and SharePoint 2010 but the steps below should be applicable to previous versions as well.</p>
<p>The steps involved are:</p>
<ul>
<li>Install SQL and SSAS clusters and set up DNS</li>
<li>Install SSRS for scale out deployment and set up network load balancer DNS</li>
<li>Setting SPNs</li>
<li>Trusting computers and service accounts for delegation</li>
<li>Configuring Reporting Services</li>
<li>Configuring SharePoint</li>
<li>Configuring Reporting Services/SharePoint integration</li>
</ul>
<h2></h2>
<h2>SQL and SSAS Clusters</h2>
<p>The good news is you really don’t need to do anything that you wouldn’t normally do when setting up a cluster for either of these two services.&#160; Create the cluster, install the services on the nodes, set up MSDTC, then create a DNS name that points at the cluster address.</p>
<p>Make sure each node in the cluster uses the same service account. For example, create a domain account called svc-SQL and use it as the service account for SQL on every node of the SQL cluster.&#160; This is required, because the SPN to be set up later can only use one account for the cluster as a whole.&#160; Do the same for Analysis Services.</p>
<h2>SSRS Cluster</h2>
<p>Here again there’s nothing out of the ordinary; the order I’d do it in is:</p>
<ul>
<li>Provision the servers, configure the NLB to load balance across them, and create a DNS entry for the RS service on the NLB</li>
<li>Install Reporting Services but don’t configure it</li>
<li>Install the SharePoint binaries on each server and&#160; join them to the farm (without making them a Web Front End)</li>
<li>Run the RS configuration tool on the first server, create a new database in SharePoint mode, then complete the rest of the configuration (report server web service, etc.)</li>
<li>Run the RS configuration on each other server, pointing them to the same Reports database.</li>
<li>After configuring all the RS servers, add all the servers to the scale-out deployment using the appropriate tab on the configuration tool.&#160; You only need to do this on one of the servers.</li>
</ul>
<p>Again, you need to make sure the webservice is running under the same account on all servers.</p>
<h2>Service Principle Names</h2>
<p>First real challenge.&#160; There are some key points to bear in mind:</p>
<ul>
<li>You create SPNs for the <em>cluster</em> name, not for the individual nodes in the cluster. Don’t create SPNs for the individual nodes as this seems to break Kerberos.</li>
<li>You must specify the port number, even if you are using the default ports for SQL Server and Analysis Services.</li>
<li>You <em>must</em> create SPNs using the fully qualified domain name of the servers, but creating them for the NetBIOS name seems to be optional – your mileage may vary on this.</li>
</ul>
<p>The SPNs you will need are for:</p>
<ul>
<li>SQL cluster</li>
<li>SSAS cluster</li>
<li>RS cluster</li>
<li>SharePoint Central Admin</li>
<li>SharePoint web sites</li>
<li>SharePoint applications such as PerformancePoint if you are using them</li>
</ul>
<p>The commands will follow this template:</p>
<p>setspn –S MSSQLSvc/[SQL cluster].[domain]:1433 [service account]   <br />setspn –S MSOLAPSvc.3/[SSAS cluster].[domain]:2383 [service account]    <br />setspn –S HTTP/[RS NLB].[domain]:80 [service account]    <br />setspn –S HTTP/[central admin server or NLB].[domain]:[port] [service account]    <br />setspn –S HTTP/[web front end or NLB].[domain]:[port] [service account]</p>
<p>Let’s build some examples of that.&#160; In this scenario, the SQL cluster is called <em>SQL</em>, the SSAS cluster is called <em>AS</em>, the SSRS load balancer is called <em>RSNLB</em>, the SharePoint Central Admin box is <em>SP01</em>, and the SharePoint web front end load balancer is called <em>WFENLB</em>. The domain is mycompany.local and all services are on their default port, other than Central Admin which is on port 8080.&#160; You’d need to run the following commands.</p>
<p>setspn –S MSSQLSvc/SQL.mycompany.local:1433 svc-SQL   <br />setspn –S MSOLAPSvc.3/AS.mycompany.local:2383 svc-AS    <br />setspn –S HTTP/RSNLB.mycompany.local:80 svc-RS    <br />setspn –S HTTP/SP01.mycompany.local:8090 svc-SPFarm    <br />setspn –S HTTP/WFENLB.mycompany.com:80 svc-SPPortal</p>
<p>Something to bear in mind: if you have created an alternative URL for your SharePoint site (such as <a href="http://intranet" rel="nofollow">http://intranet</a>), you need to create the SPN for that name instead of the WFE load balancer name. </p>
<h2></h2>
<h2>Trusting for Delegation</h2>
<p>On the DC, ensure that each of the following are trusted for Kerberos delegation:</p>
<ul>
<li>SharePoint Central Admin server</li>
<li>SharePoint web servers</li>
<li>Reporting Services servers</li>
<li>SharePoint Central Admin web application pool account</li>
<li>SharePoint web site application pool account</li>
<li>Reporting Services web app service account</li>
</ul>
<p>You can’t trust accounts until an SPN has been set up – the ‘Delegation’ tab doesn’t even appear in their account’s properties – so you have to complete this step after the SPNs have been created.</p>
<p>You might find you need to trust the SQL and SSAS boxes and service accounts.&#160; You also might find you need to trust the virtual network names for their clusters.</p>
<h2>Configure Reporting Services</h2>
<p>On each of the SSRS servers, locate the file rsreportserver.config and edit it:</p>
<ul>
<li>Find the element &lt;AuthenticationTypes&gt; and ensure it contains the element &lt;RSWindowsNegotiate/&gt;.&#160; Remove the element &lt;RSWindowsNTLM/&gt; if it exists.</li>
<li>Find the element &lt;UrlRoot&gt; and insert the web address of the SharePoint site (in the example above the correct value would be <em><a href="http://WFENLB" rel="nofollow">http://WFENLB</a></em> or <em><a href="http://intranet" rel="nofollow">http://intranet</a></em>).</li>
<li>Find the element &lt;Hostname&gt; and add the name of the SSRS cluster (in the example above the correct value would be <em>RSNLB</em>).&#160; The &lt;Hostname&gt; element may not exist, so you will need to create it – it goes inside the &lt;Service&gt; element, the same as the &lt;UrlRoot&gt; element.&#160; You would create a line such as <em>&lt;Hostname&gt;RSNLB&lt;/Hostname&gt;</em>.</li>
</ul>
<p>You must repeat for every SSRS server otherwise only some of the servers will actually work and your users will get ‘intermittent’ errors.</p>
<h2>SharePoint</h2>
<p>A trip to Central Admin should show that the RS servers have already been added to the farm.&#160; Make sure the Central Admin and all other site collections are set to use Windows Authentication in all their zones which you intend to use SSRS in.</p>
<h2>SharePoint and Reporting Services Integration</h2>
<p>SharePoint 2010 automatically installs the SSRS add in as part of the pre-requisites.&#160; For MOSS 2007, download the latest version of the add in and ensure your entire SP farm is service-packed.</p>
<p>Integration is then ready to be configured from Central Admin. In SP 2010 the config panel is at General Application Settings –&gt; Reporting Services Integration.&#160; The values you need are:</p>
<ul>
<li>Report Server Web Service URL: the address of the SSRS web service as accessed through the network load balancer, for example <em><a href="http://RSNLB/reportserver" rel="nofollow">http://RSNLB/reportserver</a></em></li>
<li>Authentication Mode: Windows Authentication</li>
<li>Credentials: The username and password of a domain account which is in the local Administrators group on the SSRS servers.&#160; If there isn’t a single account that’s in this group on every one of your SSRS boxes, use an account which is in the Administrators group for the first SSSR box in the deployment.&#160; You need to specify the username in the format [domain]\[user]</li>
</ul>
<p>After the first server is integrated, you are given the chance to add each of the other SSRS servers in the scale-out deployment to the integration.&#160; You must complete this for each server you have in the deployment.</p>
<p>Finally, you can click ‘Set server defaults’ to change any of the the properties of the integration you want to alter.</p>
<h2>Points to Bear in Mind</h2>
<p>Not working?&#160; Here’s what I check in my setup:</p>
<ul>
<li>Kerberos needs TCP and UDP ports 88 open in order to work.&#160; Is your firewall blocking that port?&#160; Try disabling the Windows firewall to check.</li>
<li>Are the clients using Internet Explorer 6 or above?&#160; Is the browser seeing that the site is in the local intranet zone? Does the zone allow integrated Windows authentication?</li>
<li>Go back over the SPNs.&#160; One mistake in your setspn command will have broken Kerberos completely.</li>
<li>Check all the accounts and computers are trusted.</li>
<li>Try navigating direct to the SSRS web service (i.e. not by opening a report in SharePoint’s interface).&#160; If you can run a report through <a href="http://rsnlb/reportserver" rel="nofollow">http://rsnlb/reportserver</a> but get an error message when doing it through SharePoint, the probable cause is with a SharePoint SPN or delegation permission not with Reporting Services.</li>
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/144/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=144&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/09/30/kerberos-in-a-clustered-and-load-balanced-bi-deployment/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>
	</item>
		<item>
		<title>Portable SSIS Configs With a Single Script</title>
		<link>http://duncansutcliffe.wordpress.com/2010/07/21/portable-ssis-configs-with-a-single-script/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/07/21/portable-ssis-configs-with-a-single-script/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 09:09:39 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Configurations]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://duncansutcliffe.wordpress.com/?p=140</guid>
		<description><![CDATA[Following from yesterday&#8217;s post, here&#8217;s how to achive SSIS configurations with a script instead of a SQL statement and a loop. Database setup is exactly the same, and the two variables for environment and configuiration database connection string are set up the same, but the package needs just a script task.  The only property for the &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/07/21/portable-ssis-configs-with-a-single-script/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=140&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Following from <a href="http://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/" target="_self">yesterday&#8217;s post</a>, here&#8217;s how to achive SSIS configurations with a script instead of a SQL statement and a loop.</p>
<p>Database setup is exactly the same, and the two variables for environment and configuiration database connection string are set up the same, but the package needs just a script task.  The only property for the script which needs to be set is MaximumErrorCount which should be set to zero.</p>
<p>This script connects to the configuration database, selects all the variables that are valid for the current package and environment and applies them.  In the script code add another <em>using</em> for <em>System.Data.SQLClient</em> then add the following:</p>
<pre>        public void Main()
        {
            // Create a variable dispenser and a variables collection
            VariableDispenser disp = this.Dts.VariableDispenser;
            Variables vars = default(Variables);

            String connString = null;
            String environmentName = null;
            String packageName = null;

            try
            {
                disp.LockForRead("User::strConfigDatabaseConnString");
                disp.LockForRead("User::strEnvironment");
                disp.LockForRead("System::PackageName");
                disp.GetVariables(ref vars);

                connString = vars["User::strConfigDatabaseConnString"].Value.ToString();
                environmentName = vars["User::strEnvironment"].Value.ToString();
                packageName = vars["System::PackageName"].Value.ToString();
                try
                {
                    // Connect to the configuration database
                    SqlConnection conn = new SqlConnection(connString);
                    conn.Open();

                    // Retrieve configuration values
                    String sql = String.Concat("select VarName, VarValue, VarType from ConfigVars where EnvironmentName = '",
                        @environmentName, "' and (PackageName = 'Sys' or PackageName = '", @packageName, "')");
                    SqlCommand command = new SqlCommand(sql, conn);

                    SqlDataReader reader = command.ExecuteReader();

                    // Loop through the reader
                    while (reader.Read())
                    {
                        String varName = reader["VarName"].ToString();
                        String varValue = reader["VarValue"].ToString();
                        String varType = reader["VarType"].ToString();

                        // Set the value for the variable
                        SetVariable(varName, varValue, varType);
                    }

                    // Tidy up
                    reader.Close();
                    reader.Dispose();
                    command.Dispose();
                    conn.Close();
                    conn.Dispose();

                }
                catch
                {
                    Dts.Events.FireWarning(0, "Set configuration variable values", "Unable to retrieve configuration values from database.", "", 0);
                }
            }
            catch
            {
                Dts.Events.FireWarning(0, "Set configuration variable values", "Unable to get configuration database connection string.", "", 0);
            }

            Dts.TaskResult = (int)ScriptResults.Success;
        }

        public void SetVariable(string varName, string varValue, string varType)
        {
            VariableDispenser disp = this.Dts.VariableDispenser;

            Variables vars = default(Variables);
            try
            {
                // Lock the variable we are going to provide a value for
                disp.LockOneForWrite(varName, ref vars);

                // Convert the value to the right type for the variable and assign it
                if (varType.ToLower() == "string")
                {
                    vars[0].Value = varValue;
                }
                else if (varType.ToLower() == "int32")
                {
                    vars[0].Value = Convert.ToInt32(varValue);
                }
                else if (varType.ToLower() == "datetime")
                {
                    // Add more strings to this array depending on the format of dates you have used in the config database
                    String[] sFormats = { "yyyy-mm-dd" };
                    DateTime dt = DateTime.ParseExact(varValue, sFormats, null, System.Globalization.DateTimeStyles.None);
                    vars[0].Value = dt;
                }
                else if (varType.ToLower() == "boolean")
                {
                    vars[0].Value = Convert.ToBoolean(varValue);
                }

                Boolean bReFire = true;
                Dts.Events.FireProgress(String.Concat("Set ", varName, " value to '", varValue, "'."), 100, 0, 0, "Set configuration variable values", ref bReFire);

            }
            catch (DtsRuntimeException ex)
            {
                Dts.Events.FireWarning(0, "Set configuration variable values", ex.Message, "", 0);
            }
        }</pre>
<p>Very simple and very flexible.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/140/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=140&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/07/21/portable-ssis-configs-with-a-single-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>
	</item>
		<item>
		<title>A Portable Alternative to Configurations in SSIS</title>
		<link>http://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/</link>
		<comments>http://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 15:55:10 +0000</pubDate>
		<dc:creator>Duncan Sutcliffe</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Configurations]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">https://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/</guid>
		<description><![CDATA[How do you configure SSIS to work across various environments such as dev, test and production?  At the very least, you are going to have a different target server/database but there are possibly different sources, different directories used for RAW files, different logging systems, different operators to notify on error and any number of other &#8230; &#8230; <a href="http://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=139&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>How do you configure SSIS to work across various environments such as dev, test and production?  At the very least, you are going to have a different target server/database but there are possibly different sources, different directories used for RAW files, different logging systems, different operators to notify on error and any number of other changes to the system between environments,</p>
<p>Using Configurations is the normal way to set up your SSIS packages with the right values needed to make it behave correctly, but when you deploy your SSIS from development to test or live, you need to change those configurations.  There’s no easy mechanism for this.  Here’s a more flexible alternative which doesn’t use Integration Services’ built-in Configuration system, but lets you write your own mechanism.  It takes a bit of setting up but you only need to do it once – then you just reuse the template package.</p>
<p>The basic principle is that for every property which needs to be configured, you create a variable and use that variable as the property value in an expression.  For example, the connection manager for your source has an expression for ‘Connection String’.  So you create a variable named <a href="mailto:‘@strSourceConnectionString’">‘@strSourceConnectionString’</a> and place that into the ConnectionString expression for the connection.  Then, the value for that variable is read from a database at runtime.  Crucially, you tune the SQL statement that retrieves variable values so that it retrieves the correct ones for your current environment.  This is what improves it over a standard Configuration.</p>
<p>The method:</p>
<p>Firstly, create a database table which will hold your variable values.  I would put this in the ETL management/audit database.  The columns you will need will be for the variable name, the variable value, the variable type, the environment and the package name (if you have variables with the same name but different values in each package).</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/07/variablevaluestable.png"><img class="wlDisabledImage" style="display:inline;border-width:0;margin:0 5px;" title="Variable Values Table" src="http://duncansutcliffe.files.wordpress.com/2010/07/variablevaluestable_thumb.png?w=290&#038;h=111" border="0" alt="Variable Values Table" width="290" height="111" /></a></p>
<p>These columns contain:</p>
<ul>
<li>The name of the variable to be configured – must be the same as the variable in SSIS.</li>
<li>The value to be assigned to the variable.</li>
<li>The data type of the variable in SSIS (because you are going to need to convert the string value to the right data type before it can be assigned).</li>
<li>The environment for which this variable should be given this value.  You can put whatever you like in this column depending on how many environments you have and what they’re called.</li>
<li>The name of the package for which this variable should be given this value.  This would need to match the name of the SSIS package exactly because it’s going to be searched for using the System::PackageName variable.  You can also use a value such as ‘SYS’ or ‘ALL’ to indicate the same value for the variable is used in all packages.</li>
</ul>
<p>Examples might be:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/07/variablevalues.png"><img class="wlDisabledImage" style="display:inline;border-width:0;" title="Variable Values" src="http://duncansutcliffe.files.wordpress.com/2010/07/variablevalues_thumb.png?w=435&#038;h=113" border="0" alt="Variable Values" width="435" height="113" /></a></p>
<p>You can see that <em>strStringVariable</em> has three entries – for the package <em>VariableTest</em> it has different values for Dev and Prod environments, and for the package <em>VariableTest2</em> it has a different value.  The other variables apply to ‘Sys’ packages which I’m going to use to mean all packages.</p>
<p>With this structure in place, we can move to SSIS.  Your package will need to know which environment you are currently in and where to find all the configuration variables; for this I think the best way is to create two variables for Environment and ConfigConnectionString, and save this as an XML configuration.  When you deploy the SSIS to a different environment, just copy the .dtsconfig file to the same location (I create a new folder on the root of C:) on the new server.  Then you only ever have to change one config value in one XML file for the environment to retrieve all the right configurations.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/07/creatingxmlconfigurationfile.png"><img class="wlDisabledImage" style="display:inline;border-width:0;margin:0 5px;" title="Creating XML configuration file" src="http://duncansutcliffe.files.wordpress.com/2010/07/creatingxmlconfigurationfile_thumb.png?w=384&#038;h=484" border="0" alt="Creating XML configuration file" width="384" height="484" /></a></p>
<p>Now create an ADO.NET connection manager and set its <em>ConnectionString </em>expression to the variable for the config database.</p>
<p>Create three string variables named strVarName, strVarValue and strVarType.  Also create the variables which you are going to add values to, remembering they need to be named exactly the same as the value in the VarName column in your config database.</p>
<p>The next thing to do is retrieve all the variable values from the config database and assign them to the variables in the package.  This could be done with a single script (<a href="http://duncansutcliffe.wordpress.com/2010/07/21/portable-ssis-configs-with-a-single-script/" target="_self">here&#8217;s how</a>) but here I am demonstrating grabbing the values then assigning them in a loop – it requires a bit less understanding of C# scripting in SSIS.</p>
<p>Add an Execute SQL Task, a ForEach Loop and a Script Task inside the loop.</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/07/ssispackagecomponents.png"><img class="wlDisabledImage" style="display:inline;border-width:0;margin:0 5px;" title="SSIS Package components" src="http://duncansutcliffe.files.wordpress.com/2010/07/ssispackagecomponents_thumb.png?w=244&#038;h=145" border="0" alt="SSIS Package components" width="244" height="145" /></a></p>
<p>The SQL task uses the config database connection, and its SQL statement is something like:</p>
<p><span style="font-family:Courier New;">select VarName, VarValue,VarType from Configs<br />
where EnvironmentName = @envName and (PackageName in (@pacName, ‘Sys’))</span></p>
<p>Map the @envName parameter to your <em>Environment</em> variable and the @pacName to the System::PackageName variable.  Set the ResultSet property to <em>FullResultSet</em> and place the result set into an object variable named <em>objVariables</em>.</p>
<p>Properties for the ForEach loop are:</p>
<ul>
<li>Enumerator: Foreach ADO Enumerator</li>
<li>ADO object source vasriable: User::objVariables</li>
<li>Variable Mappings: User::strVarName, User::strVarValue, User::strVarType</li>
</ul>
<p>On the loop and the script, set the <em>MaximumErrorCount</em> property to zero.  This is because you will get errors if the variable you are trying to assign a value to doesn’t actually exist in the package – but you don’t want to crash the whole package because of this.</p>
<p>The basis of the script code you need is:</p>
<p><span style="font-family:Courier New;">        public void Main()<br />
        {</span></p>
<p><span style="font-family:Courier New;">            // Create a variable dispenser and a variables collection<br />
            VariableDispenser disp = this.Dts.VariableDispenser;<br />
            Variables vars = default(Variables);<br />
           <br />
            string varName = null;<br />
            string varValue = null;<br />
            string varType = null;</span></p>
<p><span style="font-family:Courier New;">            try<br />
            {<br />
                // Lock and assign variables<br />
                disp.LockForRead(&#8220;User::strVarName&#8221;);<br />
                disp.LockForRead(&#8220;User::strVarValue&#8221;);<br />
                disp.LockForRead(&#8220;User::strVarType&#8221;);<br />
                disp.GetVariables(ref vars);<br />
                varName = String.Concat(&#8220;User::&#8221;, vars["User::strVarName"].Value.ToString());<br />
                varValue = vars["User::strVarValue"].Value.ToString();<br />
                varType = vars["User::strVarType"].Value.ToString();</span></p>
<p><span style="font-family:Courier New;">                vars.Unlock();<br />
            }<br />
            catch<br />
            {<br />
                Dts.Events.FireWarning(0, &#8220;Set configuration variable values&#8221;, &#8220;Unable to lock variables.&#8221;, &#8220;&#8221;, 0);<br />
            }</span></p>
<p><span style="font-family:Courier New;">            // Call method which assigns values to SSIS variables<br />
            SetVariable(varName, varValue, varType);</span></p>
<p><span style="font-family:Courier New;">            // Finish<br />
            Dts.TaskResult = (int)ScriptResults.Success;<br />
        }</span></p>
<p><span style="font-family:Courier New;">        public void SetVariable(string varName, string varValue, string varType)<br />
        {<br />
            VariableDispenser disp = this.Dts.VariableDispenser;</span></p>
<p><span style="font-family:Courier New;">            Variables vars = default(Variables);<br />
            try<br />
            {<br />
                // Lock the variable we are going to provide a value for<br />
                disp.LockOneForWrite(varName, ref vars);</span></p>
<p><span style="font-family:Courier New;">                // Convert the value to the right type for the variable and assign it<br />
                if (varType.ToLower() == &#8220;string&#8221;)<br />
                {<br />
                    vars[0].Value = varValue;<br />
                }<br />
                else if (varType.ToLower() == &#8220;int32&#8243;)<br />
                {<br />
                    vars[0].Value = Convert.ToInt32(varValue);<br />
                }<br />
                else if (varType.ToLower() == &#8220;datetime&#8221;)<br />
                {<br />
                    // Add more strings to this array depending on the format of dates you have used in the config database<br />
                    String[] sFormats = {&#8220;yyyy-mm-dd&#8221;};<br />
                    DateTime dt = DateTime.ParseExact(varValue, sFormats, null, System.Globalization.DateTimeStyles.None);<br />
                    vars[0].Value = dt;<br />
                }</span></p>
<p><span style="font-family:Courier New;">                Boolean bReFire = true;<br />
                Dts.Events.FireProgress(String.Concat(&#8220;Set &#8220;, varName, &#8221; value to &#8216;&#8221;, varValue, &#8220;&#8216;.&#8221;), 100, 0, 0, &#8220;Set configuration variable values&#8221;, ref bReFire);</span></p>
<p><span style="font-family:Courier New;">            }<br />
            catch (DtsRuntimeException ex)<br />
            {<br />
                Dts.Events.FireWarning(0, &#8220;Set configuration variable values&#8221;, ex.Message, &#8220;&#8221;, 0);<br />
            }</span></p>
<p><span style="font-family:Courier New;">            // Unlock variables<br />
            vars.Unlock();<br />
        }<br />
    }<br />
</span></p>
<p>Note that I have used a VariableDispenser where required, so you don’t need to add any variables to the ReadOnlyVariables or ReadWriteVariables.  This script only covers string, integer and datetime variables – if you’ve got other types you’ll need to add additional condition handlers to the <span style="font-family:Courier New;">if…elseif</span> block to do the conversions required.</p>
<p>What happens when you run the package?  If you set the strEnvironmentName variable to ‘Dev’, you get this:</p>
<p><a href="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesfordevelopment.png"><img class="wlDisabledImage" style="display:inline;border:0;" title="Variables assigned values for development" src="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesfordevelopment_thumb.png?w=452&#038;h=74" border="0" alt="Variables assigned values for development" width="452" height="74" /></a></p>
<p>If you set the value to ‘Prod’ you get different values:<br />
<a href="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesforproduction.png"><img class="wlDisabledImage" style="display:inline;border:0;margin:0 5px;" title="Variables assigned values for production" src="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesforproduction_thumb.png?w=454&#038;h=72" border="0" alt="Variables assigned values for production" width="454" height="72" /></a></p>
<p>So, everything is completely portable between environments.</p>
<p>Let me know (Twitter: @DuncanSutcliffe) if this works for you or if it doesn’t.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/duncansutcliffe.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/duncansutcliffe.wordpress.com/139/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=duncansutcliffe.wordpress.com&#038;blog=12833890&#038;post=139&#038;subd=duncansutcliffe&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://duncansutcliffe.wordpress.com/2010/07/20/a-portable-alternative-to-configurations-in-ssis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/acea5f47aa46507e21e8efaa7a88813a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Duncan Sutcliffe</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/variablevaluestable_thumb.png" medium="image">
			<media:title type="html">Variable Values Table</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/variablevalues_thumb.png" medium="image">
			<media:title type="html">Variable Values</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/creatingxmlconfigurationfile_thumb.png" medium="image">
			<media:title type="html">Creating XML configuration file</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/ssispackagecomponents_thumb.png" medium="image">
			<media:title type="html">SSIS Package components</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesfordevelopment_thumb.png" medium="image">
			<media:title type="html">Variables assigned values for development</media:title>
		</media:content>

		<media:content url="http://duncansutcliffe.files.wordpress.com/2010/07/variablesassignedvaluesforproduction_thumb.png" medium="image">
			<media:title type="html">Variables assigned values for production</media:title>
		</media:content>
	</item>
	</channel>
</rss>
