<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Salvo(z)</title>
	
	<link>http://salvoz.com/blog</link>
	<description>Aviation, Fitness and Technology</description>
	<lastBuildDate>Mon, 07 May 2012 20:25:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SalvoZ" /><feedburner:info uri="salvoz" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>SSAS: Duplicate Attribute Key Error</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/-7DKNSQNDEU/</link>
		<comments>http://salvoz.com/blog/2012/05/07/ssas-duplicate-attribute-key-error/#comments</comments>
		<pubDate>Mon, 07 May 2012 20:19:42 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=964</guid>
		<description><![CDATA[One type of error that arises occasionally during SSAS cube processing is the ‘duplicate attribute key’ error.  The error message is similar to the following: &#60;Warning WarningCode=&#8221;1092550658&#8243; Description=&#8221;Errors in the OLAP storage engine: A duplicate attribute key has been found &#8230; <a href="http://salvoz.com/blog/2012/05/07/ssas-duplicate-attribute-key-error/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One type of error that arises occasionally during SSAS cube processing is the ‘duplicate attribute key’ error.  The error message is similar to the following:</p>
<p><em>&lt;Warning WarningCode=&#8221;1092550658&#8243; Description=&#8221;Errors in the OLAP storage engine: A duplicate attribute key has been found when processing: Table: &#8216;dbo_DimClaim&#8217;, Column: &#8216;ClaimCanceledReasonCode&#8217;, Value: &#8221;. The attribute is &#8216;Claim Canceled Reason Code&#8217;.&#8221; Source=&#8221;Microsoft SQL Server 2008 R2 Analysis Services&#8221; HelpFile=&#8221;" /&gt;</em></p>
<p>In the example above, the error was due to a carriage return stored in the ClaimCanceledReasonCode column.  During processing, SSAS converted the carriage return to an empty string and since the empty string was already processed as a key value from another row the ‘duplicate attribute key’ error was generated.</p>
<p>When I first encountered this error, I was confused because a Select Distinct query should never return a duplicate in the first place.  I then discovered that SSAS maps certain types of values (e.g. NULL, carriage returns, etc.) to an empty string which causes this error to arise if there is another row in the dataset that contains an empty string value.  In my experience, this is the most common cause of this error.</p>
<p>The following blog post provides a good overview of the various scenarios that may cause the duplicate attribute key error and how to avoid them:  <a title="http://ms-olap.blogspot.com/2009/11/duplicate-attribute-key-has-been-found.html" href="http://ms-olap.blogspot.com/2009/11/duplicate-attribute-key-has-been-found.html">http://ms-olap.blogspot.com/2009/11/duplicate-attribute-key-has-been-found.html</a>.</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/-7DKNSQNDEU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/05/07/ssas-duplicate-attribute-key-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/05/07/ssas-duplicate-attribute-key-error/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssas-duplicate-attribute-key-error</feedburner:origLink></item>
		<item>
		<title>Visual Studio 11 Beta, Code Contracts and Strong Naming</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/fLLhns9o3G4/</link>
		<comments>http://salvoz.com/blog/2012/04/08/visual-studio-11-beta-code-contracts-and-strong-naming/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 00:31:31 +0000</pubDate>
		<dc:creator>Adam Salvo</dc:creator>
				<category><![CDATA[Tooling]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">https://salvoz.com/blog/2012/04/08/visual-studio-11-beta-code-contracts-and-strong-naming/</guid>
		<description><![CDATA[There is a bug in the Visual Studio 11 beta installer which incorrectly sets the path to the Strong Name tool (sn.exe) in the code contracts targets file. When building an application with Code Contracts enabled, and the assembly is &#8230; <a href="http://salvoz.com/blog/2012/04/08/visual-studio-11-beta-code-contracts-and-strong-naming/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There is a bug in the Visual Studio 11 beta installer which incorrectly sets the path to the Strong Name tool (sn.exe) in the code contracts targets file. When building an application with Code Contracts enabled, and the assembly is signed, you will get an error 9009 from MS Build, indicating a 3rd party tool (CCRewriter in this instance) failed. This is because the CCRewriter can not find the sn.exe. </p>
<p>The fix is pretty easy, just change the Code Contracts targets file to the correct path. The targets file is located at C:\Program Files (x86)\Microsoft\Contracts\MsBuild\v4.0\Microsoft.CodeContracts.targets. Line 267 should be changed to:</p>
<p>&lt;CodeContractsSnExe&gt;&#8221;$(CodeContractsSdkPath)Bin\NETFX 4.0 Tools\sn.exe&#8221;&lt;/CodeContractsSnExe&gt;</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/fLLhns9o3G4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/04/08/visual-studio-11-beta-code-contracts-and-strong-naming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/04/08/visual-studio-11-beta-code-contracts-and-strong-naming/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=visual-studio-11-beta-code-contracts-and-strong-naming</feedburner:origLink></item>
		<item>
		<title>SSAS: Processing Cube Dimensions and Measures in SSMS</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/4aUTBNEvR-Y/</link>
		<comments>http://salvoz.com/blog/2012/04/02/ssas-processing-cube-dimensions-and-measures-in-ssms/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 17:03:48 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/04/02/ssas-processing-cube-dimensions-and-measures-in-ssms/</guid>
		<description><![CDATA[My co-worker showed me an easy way to process all SQL Server Analysis Services (SSAS)cube dimensions (or measures) from the GUI interface in SQL Server Management Studio (SSMS). To process all dimensions: 1.&#160; Connect to an SSAS instance in SSMS. &#8230; <a href="http://salvoz.com/blog/2012/04/02/ssas-processing-cube-dimensions-and-measures-in-ssms/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My co-worker showed me an easy way to process all SQL Server Analysis Services (SSAS)cube dimensions (or measures) from the GUI interface in SQL Server Management Studio (SSMS).</p>
<p><strong>To process all dimensions:</strong></p>
<p>1.&nbsp; Connect to an SSAS instance in SSMS.</p>
<p>2. Expand the appropriate node / cube.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb.png" width="170" height="151"></a></p>
<p>3. Select ‘Dimensions’ and in the SSMS menu at the top select ‘View’ &gt; ‘Object Explorer Details’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image1.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb1.png" width="165" height="244"></a></p>
<p>4.&nbsp; You will then see the following window with a list of the dimensions.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML659e975.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML659e975" border="0" alt="SNAGHTML659e975" src="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML659e975_thumb.png" width="206" height="244"></a></p>
<p>5. Select all dimensions by first clicking on the top dimension in the list, hold down the ‘Shift’ key and then click the last dimension.&nbsp; You should now have all the dimensions selected as shown below.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image2.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb2.png" width="244" height="193"></a></p>
<p>6.&nbsp; Right click anywhere on the dimensions and then click ‘Process’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb3.png" width="119" height="78"></a></p>
<p>7.&nbsp; You should now see a ‘Process Object (s)’ window.&nbsp; Update the ‘Process Option’ for each dimension if needed and then click ‘OK’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML661a093.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML661a093" border="0" alt="SNAGHTML661a093" src="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML661a093_thumb.png" width="388" height="302"></a></p>
<p>8.&nbsp; A dimension ‘Processing Progress’ window is displayed. If the processing completes successfully, you should see a ‘Process succeeded’ message.&nbsp;&nbsp;&nbsp; When finished, close the window. </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb4.png" width="144" height="60"></a></p>
<p><strong>The steps to process all the measures are almost identical:</strong></p>
<p>1.&nbsp; Connect to an SSAS instance in SSMS.</p>
<p>2. Expand the appropriate node / cube.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image5.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb5.png" width="170" height="151"></a></p>
<p>3. Expand the Cubes node to the ‘Measure Groups’ level.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image6.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb6.png" width="202" height="115"></a></p>
<p>4.&nbsp; Select ‘Measure Groups’ and in the SSMS menu at the top select ‘View’ &gt; ‘Object Explorer Details’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image8.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb7.png" width="165" height="244"></a></p>
<p>5.&nbsp; You will then see the following window with a list of the measure groups.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML68fd866.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML68fd866" border="0" alt="SNAGHTML68fd866" src="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML68fd866_thumb.png" width="230" height="143"></a></p>
<p>6.&nbsp; Select all dimensions by first clicking on the top measure in the list, hold down the ‘Shift’ key and then click the last measure.&nbsp; You should now have all the measures selected.</p>
<p>7.&nbsp; Right click anywhere on the measures and then click ‘Process’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image9.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb8.png" width="119" height="78"></a></p>
<p>8.&nbsp; You should now see a ‘Process Object (s)’ window.&nbsp; Update the ‘Process Option’ for each measure if needed and then click ‘OK’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML6949cbd.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML6949cbd" border="0" alt="SNAGHTML6949cbd" src="http://salvoz.com/blog/wp-content/uploads/2012/04/SNAGHTML6949cbd_thumb.png" width="407" height="295"></a></p>
<p>9.&nbsp; A measure ‘Processing Progress’ window is displayed. If the processing completes successfully, you should see a ‘Process succeeded’ message.&nbsp;&nbsp;&nbsp; When finished, close the window. </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/04/image10.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/04/image_thumb9.png" width="144" height="60"></a></p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/4aUTBNEvR-Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/04/02/ssas-processing-cube-dimensions-and-measures-in-ssms/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/04/02/ssas-processing-cube-dimensions-and-measures-in-ssms/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssas-processing-cube-dimensions-and-measures-in-ssms</feedburner:origLink></item>
		<item>
		<title>PowerShell: Check for Existence of File and Send Email If File Does Not Exist</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/GrEvBwqWH3g/</link>
		<comments>http://salvoz.com/blog/2012/03/28/powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 15:09:09 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Programming (Other)]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/03/28/powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist/</guid>
		<description><![CDATA[I created a PowerShell script that runs as the first step in a SQL Server Agent Job.&#160; The script checks for the existence of some files and sends an email and throws an exception to terminate the job if any &#8230; <a href="http://salvoz.com/blog/2012/03/28/powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I created a PowerShell script that runs as the first step in a SQL Server Agent Job.&nbsp; The script checks for the existence of some files and sends an email and throws an exception to terminate the job if any of the files do not exist.&nbsp; An example of the code is included below.</p>
<p align="left">#File Locations<br />$file1 = <a href="file://\\yourfileshare\file1.txt">\\yourfileshare\file1.txt</a></p>
<p align="left">$file2 = <a href="file://\\yourfileshare\file2.txt">\\yourfileshare\file2.txt</a></p>
<p>#Check for Existence of Files<br />$file1Exists = Test-Path $file1</p>
<p>$file2Exists = Test-Path $file2</p>
<p>#Email Settings<br />$emailFrom = “<a href="mailto:&ldquo;EmailFromAddress@yourdomain.com">EmailFromAddress@yourdomain.com</a>”<br />$emailTo = “<a href="mailto:&ldquo;EmailToAddress@yourdomain.com">EmailToAddress@yourdomain.com</a>”<br />$subject = &#8220;Missing Files&#8221;<br />$body = &#8220;The following files are missing:`r`n&#8221;<br />$smtpServer = &#8220;123.45.67.890&#8243;<br />$smtp = new-object Net.Mail.SmtpClient($smtpServer)</p>
<p>If ($file1Exists -and $file2Exists)<br />{&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; #Do Nothing<br />}<br />Else <br />{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; #Generate Text for Email Body<br />&nbsp;&nbsp;&nbsp;&nbsp; If (-not $file1Exists) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $body += &#8220;`r`n&#8221; + $file1 + &#8221; .&#8221;<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; If (-not $file2Exists) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $body += &#8220;`r`n&#8221; + $file2 + &#8221; .&#8221;<br />&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; #Send Email<br />&nbsp;&nbsp;&nbsp;&nbsp; $smtp.Send($emailFrom, $emailTo, $subject, $body)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; #Throw Exception to Terminate Job<br />&nbsp;&nbsp;&nbsp;&nbsp; throw &#8220;Missing Files&#8221;</p>
<p>}</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/GrEvBwqWH3g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/03/28/powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/03/28/powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=powershell-check-for-existence-of-file-and-send-email-if-file-does-not-exist</feedburner:origLink></item>
		<item>
		<title>SSIS: Script Component Asynchronous Transformation</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/Ob-kJsBralM/</link>
		<comments>http://salvoz.com/blog/2012/03/20/ssis-script-component-asynchronous-transformation/#comments</comments>
		<pubDate>Tue, 20 Mar 2012 18:28:11 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/03/20/ssis-script-component-asynchronous-transformation/</guid>
		<description><![CDATA[The SSIS script component can be configured to use synchronous or asynchronous outputs.&#160; If the script component is configured for synchronous outputs, then each input row is processed as it passes through the component.&#160; Asynchronous outputs can be configured to &#8230; <a href="http://salvoz.com/blog/2012/03/20/ssis-script-component-asynchronous-transformation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The SSIS script component can be configured to use synchronous or asynchronous outputs.&nbsp; If the script component is configured for synchronous outputs, then each input row is processed as it passes through the component.&nbsp; Asynchronous outputs can be configured to wait until multiple input rows have been received before processing.</p>
<p>I recently used an asynchronous transform to group rows based on two column values (ShipToNumber and NoteDateTime) and then concatenated the values from a third column (Note) and output a single row to the downstream data flow.</p>
<p>After configuring the data source to extract the desired data, the first step is to add a Sort component to sort the rows based on the two columns we wish to group by (in this example I also needed to sort on the sequence column so the Note column values are concatenated in the correct order).</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/image.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/03/image_thumb.png" width="178" height="160"></a></p>
<p>The Sort component is configured as follows:</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML191332.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTML191332" border="0" alt="SNAGHTML191332" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML191332_thumb.png" width="609" height="406"></a></p>
<p>In this example, I am sorting by three input columns in ascending order.&nbsp; The remaining columns are configured to pass through the component.&nbsp; Performing this sort functionality is necessary so the rows are sent in the desired order to the Script Component.</p>
<p>Now we will add a Script Component to the data flow.&nbsp; The Script Component is represented by the following icon in the toolbox.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML13a9f5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML13a9f5" border="0" alt="SNAGHTML13a9f5" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML13a9f5_thumb.png" width="184" height="24"></a></p>
<p>When you drag the script component onto the data flow surface, you will be prompted to select one of the following options:</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/image1.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2012/03/image_thumb1.png" width="244" height="221"></a></p>
<p>In this case you will want to select the ‘Transformation’ option if it is not already selected and click ‘OK’.</p>
<p>Double click on the Script Component to configure its properties.</p>
<p><strong>Setting the Script Language</strong></p>
<p>In this example, I am using C# as the script language.&nbsp; You can change the script language by setting the <strong>ScriptLanguage</strong> property on the Script page of the editor as shown below.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML2420e8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML2420e8" border="0" alt="SNAGHTML2420e8" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML2420e8_thumb.png" width="629" height="447"></a></p>
<p><strong>Configuring Input Columns</strong></p>
<p>The Script Component has one configured input by default named Input0.&nbsp; In this example, that is sufficient for our needs.&nbsp;&nbsp; We will now need to add columns to this input.&nbsp; All columns we want to flow downstream to subsequent components should be included in the input.&nbsp; In this example we are including all available columns as Input Columns, except for the Sequence column.&nbsp; All input columns are set to ‘Read Only’, since their values should not change.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML2d8813.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML2d8813" border="0" alt="SNAGHTML2d8813" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML2d8813_thumb.png" width="630" height="413"></a></p>
<p><strong>Configuring the Output Columns</strong></p>
<p>Once we have selected the appropriate Input Columns, we now will configure the Inputs and Outputs.&nbsp; Select the ‘Inputs and Outputs’ tab on the left-hand side.</p>
<p>First, we need to configure Output 0 to be an asynchronous output.&nbsp; Click on ‘Output 0’ in the ‘Inputs and outputs:’ hierarchy.&nbsp; Set the ‘SynchronousInputID’ property to ‘None’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTMLe9db65.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTMLe9db65" border="0" alt="SNAGHTMLe9db65" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTMLe9db65_thumb.png" width="638" height="353"></a></p>
<p>Now we can add the Output columns.&nbsp; To add a column, you first need to select ‘Output 0’ in the ‘Inputs and outputs:’ hierarchy.&nbsp; Then click the ‘Add Column’ button.&nbsp; You will be prompted to give the column a name and then select the correct data type in the right hand panel.&nbsp; In this example, the output columns are the same as the input columns with the exception of the ‘Note’ column which is re-named to ‘CombinedNote’.&nbsp; CombinedNote is a concatenation of the Note column of the input rows. </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML3ac82f.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTML3ac82f" border="0" alt="SNAGHTML3ac82f" src="http://salvoz.com/blog/wp-content/uploads/2012/03/SNAGHTML3ac82f_thumb.png" width="636" height="370"></a></p>
<p><strong>Modifying the Script Code</strong></p>
<p>Now we are ready to modify the code in the script.&nbsp; First, click the Script tab in the left-hand side of the Editor window.&nbsp; Next, click the ‘Edit Script’ button.</p>
<p>In public class ScriptMain : UserComponent, we first need to create some private member variables that represent the columns in our output.&nbsp; We also need a Boolean variable that is used as a flag to check for the first row.</p>
<p>private string CombinedNote; <br />private int ShipToNumber; <br />private DateTime NoteDateTime; <br />private DateTime Timestamp; <br />private string User; <br />private bool firstRow = true;</p>
<p>We must then update the Input0_ProcessInputRow(Input0Buffer Row) method.&nbsp; In this example, we are ‘grouping’ the input rows by the columns ShipToNumber and NoteDateTime.&nbsp; The rows are already sorted by the Sort component in ascending order based on the ShipToNumber and NoteDateTime.&nbsp;&nbsp; </p>
<p>If we are processing the first row we first need to store the values of these columns into the class variables.&nbsp; For all subsequent rows, we check to see if the value of the current row’s ShipToNumber and NoteDateTime matches what we have stored in the class variables.&nbsp; If they are the same, then we concatenate the value from the Note column to the ConcatenatedNote variable.&nbsp; We continue to process rows, concatenating the value of the Note column to ConcatenatedNote for each row, until we come across a row with a new ShipToNumber or NoteDateTime.&nbsp; </p>
<p>When we find a row with new values, we add a row to the OutputBuffer0 and then assign the values of the OutputBuffer0 rows to the values stored in our class variables.&nbsp; We then update the class variables with the values from the current row.&nbsp; </p>
<p>The code is shown below.</p>
<p><font size="2">public override void Input0_ProcessInputRow(Input0Buffer Row) <br />&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp; if ((Row.ShipToNumber == ShipToNumber &amp;&amp; Row.NoteDateTime == NoteDateTime) || firstRow) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CombinedNote += (Row.Note_IsNull ? &#8220;&#8221; : Row.Note); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShipToNumber = (int)Row.ShipToNumber; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NoteDateTime = Row.NoteDateTime; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Timestamp = Row.Timestamp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User = Row.User; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; firstRow = false; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.AddRow(); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.NoteDateTime = NoteDateTime; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.Timestamp = Timestamp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.ShipToNumber = ShipToNumber; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.User = User; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.CombinedNote.AddBlobData( <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Text.UnicodeEncoding.Unicode.GetBytes(CombinedNote ?? &#8220;&#8221;)); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShipToNumber = (int)Row.ShipToNumber ; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NoteDateTime = Row.NoteDateTime; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Timestamp = Row.Timestamp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CombinedNote = (Row.Note_IsNull ? &#8220;&#8221; : Row.Note); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User = Row.User; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; }</font></p>
<p>Just as we needed special processing for the first row, we also need some special processing for the last row.&nbsp; This involves overriding the FinishOutputs method.&nbsp; We first must add a row to our OutputBuffer0 and then assign the values of the OutputBuffer0 output columns to the values in our class variables as shown below. </p>
<p><font size="2">public override void FinishOutputs() <br />{ <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.AddRow(); <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.NoteDateTime = NoteDateTime; <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.Timestamp = Timestamp; <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.ShipToNumber = ShipToNumber; <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.User = User; <br />&nbsp;&nbsp;&nbsp;&nbsp; Output0Buffer.CombinedNote.AddBlobData( <br />&nbsp;&nbsp;&nbsp;&nbsp; System.Text.UnicodeEncoding.Unicode.GetBytes(CombinedNote ?? &#8220;&#8221;)); <br />&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; base.FinishOutputs(); <br />} <br /></font></p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/Ob-kJsBralM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/03/20/ssis-script-component-asynchronous-transformation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/03/20/ssis-script-component-asynchronous-transformation/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssis-script-component-asynchronous-transformation</feedburner:origLink></item>
		<item>
		<title>SSAS: Currency Conversion in MDX Script</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/EdAblyCdGRA/</link>
		<comments>http://salvoz.com/blog/2012/02/08/ssas-currency-conversion-in-mdx-script/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 03:25:32 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/02/08/ssas-currency-conversion-in-mdx-script/</guid>
		<description><![CDATA[In my prior blog post, I provided some details regarding currency conversion via measure expressions in SSAS.&#160;&#160;&#160; I recently attempted to implement currency conversion for some inventory measures and discovered a limitation with measure expressions &#8211; they do not work &#8230; <a href="http://salvoz.com/blog/2012/02/08/ssas-currency-conversion-in-mdx-script/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In my prior blog post, I provided some details regarding currency conversion via measure expressions in SSAS.&nbsp;&nbsp;&nbsp; I recently attempted to implement currency conversion for some inventory measures and discovered a limitation with measure expressions &#8211; they do not work for measures with a ‘Last non-empty value’ aggregation.&nbsp; As an alternative to measure expressions, the currency conversion may be implemented in the cube’s MDX script.&nbsp; </p>
<p>The basic expression for currency conversion is:</p>
<p><font size="2">[Measure in Target Currency] = </font><font size="2">[Measure in Source Currency] * [Currency Conversion Rate]</font></p>
<p>In this example, we have a measure that represents a value converted from the source currency to a target currency.&nbsp; The initial value of this measure is set to the source currency (specified by the Source column).&nbsp; </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/SNAGHTML10b77c.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML10b77c" border="0" alt="SNAGHTML10b77c" src="http://salvoz.com/blog/wp-content/uploads/2012/02/SNAGHTML10b77c_thumb.png" width="244" height="121"></a></p>
<p>Now, we need to overwrite the measure’s value in the MDX script so it represents the measure in the target currency (in this example, the measure we’re overwriting is called ‘Quantity Available Cost Converted’. The measure ‘Quantity Available Cost Local’ is in the original/source currency).&nbsp; The target currency is selected by the end-user.</p>
<p>SCOPE([Measures].[Quantity Available Cost Converted] <br />,LEAVES([Source Currency]) <br />,LEAVES([Destination Currency]) <br />,LEAVES([Currency Rate Type]) <br />,LEAVES([Dates])); <br />THIS = [Measures].[Quantity Available Cost Local] * [Measures].[Currency Rate Ov]; <br />END SCOPE;</p>
<p>The SCOPE function ensures that we are only affecting the portion of the cube specified in the function.&nbsp; In this case, the function overwrites the measure Quantity Available Cost Converted where it intersects the leaves of the Source Currency, Destination (target) Currency, Currency Rate Type and Dates dimensions.&nbsp; The LEAVES function is important since the measure uses the ‘Last Non-Empty Value’ aggregation and is therefore semi-additive.&nbsp; We only want to perform the calculation at the leaf level and not use the aggregations.</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/EdAblyCdGRA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/02/08/ssas-currency-conversion-in-mdx-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/02/08/ssas-currency-conversion-in-mdx-script/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssas-currency-conversion-in-mdx-script</feedburner:origLink></item>
		<item>
		<title>SSAS: Currency Conversion Using Measure Expressions</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/o5ocnB2saw8/</link>
		<comments>http://salvoz.com/blog/2012/02/01/ssas-currency-conversion/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 22:45:00 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/02/01/ssas-currency-conversion/</guid>
		<description><![CDATA[Currency conversions can be implemented several ways as part of a business intelligence solution.  In some scenarios it may be preferable to implement the conversion in the ETL, while in other scenarios it might make more sense to implement the &#8230; <a href="http://salvoz.com/blog/2012/02/01/ssas-currency-conversion/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Currency conversions can be implemented several ways as part of a business intelligence solution.  In some scenarios it may be preferable to implement the conversion in the ETL, while in other scenarios it might make more sense to implement the conversion in the cube itself.  Implementing currency conversion in the ETL is only feasible when the source currency will be converted to one or two target/destination currencies.  If your business requirements dictate that users need the ability to select from a large set of target currencies, then you will likely need to implement currency conversion in the cube.</p>
<p>This blog post describes implementing currency conversion in an SSAS cube via Measure Expressions.  In this scenario, the data is collected and reported in multiple currencies.</p>
<p><strong>Dimensional Modeling</strong></p>
<p>The dimensions and facts are modeled as follows:</p>
<ul>
<li><strong>Source Currency Dimension</strong>
<ul>
<li>Attributes:  CurrencyCodeKey, CurrencyCode (e.g. USD)</li>
</ul>
</li>
<li><strong>Target / Destination Currency Dimension</strong>
<ul>
<li>Attributes:  CurrencyCodeKey, CurrencyCode (e.g. USD)</li>
</ul>
</li>
<li><strong>Date/Time Dimension</strong>
<ul>
<li>Attributes: DateKey, Date, Fiscal Week, Fiscal Month, etc.</li>
</ul>
</li>
<li><strong>Exchange Rate Measure Group</strong> <span style="font-size: x-small;"><em>(labeled FactConversionMRate in the diagram below)</em> </span>
<ul>
<li>Attributes: SourceCurrencyKey, DestinationCurrencyKey, CurrencyRate</li>
</ul>
</li>
<li><strong>Transactional Measure Group(s)</strong> <em><span style="font-size: x-small;">(e.g. sales data, purchase order data, etc.)</span></em>
<ul>
<li>Relationship with the Date/Time dimension (DateKey) and Source Currency Dimension (CurrencyCodeKey).</li>
</ul>
</li>
</ul>
<p>The diagram below shows the relationships between the fact and dimension tables.  I did not include the table with transactional data in the diagram.  The transactional data will generally have a relationship to the DimDate table, DimSourceCurrency, and DimCurrencyRateType tables.  The currency rate type is only necessary if  several different types of conversion rates are used. </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/CurrencySchema.jpg"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="CurrencySchema" src="http://salvoz.com/blog/wp-content/uploads/2012/02/CurrencySchema_thumb.jpg" alt="CurrencySchema" width="501" height="311" border="0" /></a></p>
<p><strong>SSAS Currency Conversion</strong></p>
<p>Once you have the data loaded into the physical fact and dimension tables, you can begin to modify the cube.  The actual conversion calculations will be performed via Measure Expressions in SSAS.</p>
<p>The first step is to add the fact and dimension tables to the data source view.</p>
<p>Next, you will need to create a measure group that represents the conversion rate.  In the example diagram above, the measure group is based off the FactConversionMRate table with two measures CurrencyRateOv and CurrencyRateDiv.  These measures are the rates used to convert from the ‘FromCurrency’ to the ‘ToCurrency’ and vice versa.</p>
<p>You will also need to include dimensions for each of the dimension tables shown in the diagram above.  This includes date, source currency, target / destination currency and currency rate type (optional).  The source currency and target currency have one attribute: currency code.  The currency rate type dimension also has one attribute: currency rate type key. </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/image.png"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://salvoz.com/blog/wp-content/uploads/2012/02/image_thumb.png" alt="image" width="244" height="193" border="0" /></a></p>
<p>The Source Currency Code and Destination Currency Code attributes have their KeyColumn set to CurrencyCodeKey and NameColumn set to CurrencyCode.  Similarly, the Currency Rate Type Key attribute has the KeyColumn set to CurrencyRateTypeKey and the NameColumn set to CurrencyRateType.</p>
<p>Both the source currency and currency rate type dimensions may be hidden (Visible set to False) since the values are already defined in the transactional data and should not be modified by the end-user.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/image1.png"><img style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://salvoz.com/blog/wp-content/uploads/2012/02/image_thumb1.png" alt="image" width="244" height="180" border="0" /></a></p>
<p>The Destination Currency dimension should be visible so the end-user has the ability to select the desired target currency.</p>
<p>After creating the measure groups and dimensions in the cube, you will need to modify the relationships in the ‘Dimension Usage’ tab.  The relationships should be configured as follows <em>(I am only displaying the measure groups and dimensions that relate to the currency conversion.)</em>:</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/image2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://salvoz.com/blog/wp-content/uploads/2012/02/image_thumb2.png" alt="image" width="442" height="162" border="0" /></a></p>
<p>The Many-to-Many relationship is based on the Conversion Rate measure group.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/image3.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://salvoz.com/blog/wp-content/uploads/2012/02/image_thumb3.png" alt="image" width="444" height="142" border="0" /></a></p>
<p>Once the relationships between the facts and dimensions are established, the measure expressions may be added.</p>
<p>First, create a new measure in the transactional measure group (e.g. sales).  Select the appropriate Source Table and Source Column.  The source column contains the value you want to convert to the target currency.</p>
<p>In the measure properties ‘Measure Expression’ field, enter in the appropriate calculation to perform the currency conversion.  Something similar to that shown below:</p>
<p>[Extended Price] * [Currency Rate]</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2012/02/image4.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://salvoz.com/blog/wp-content/uploads/2012/02/image_thumb4.png" alt="image" width="244" height="129" border="0" /></a></p>
<p>You now have all the pieces in place to perform currency conversions in SSAS.</p>
<p><strong>Summary</strong></p>
<p>This blog post demonstrates one approach to implementing currency conversions.  Many alternative approaches exist in BI.  It is often possible to implement currency conversion directly in the ETL as opposed to SSAS.  This is especially true if you are converting between a small number of source and target currencies.  If your users need the ability to convert to a wide range of target currencies, it may be ideal to implement the currency conversion directly in SSAS using an approach similar to that described in this blog post.</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/o5ocnB2saw8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/02/01/ssas-currency-conversion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/02/01/ssas-currency-conversion/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssas-currency-conversion</feedburner:origLink></item>
		<item>
		<title>SQL Server 2012 Tabular Models vs. PowerPivot</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/UlkHctxVxW4/</link>
		<comments>http://salvoz.com/blog/2012/01/15/sql-server-2012-tabular-models-vs-powerpivot/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 00:29:00 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Tabular Models]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2012/01/15/sql-server-2012-tabular-models-vs-powerpivot/</guid>
		<description><![CDATA[I recently installed SQL Server 2012 and began exploring the tabular models.&#160; At first glance, they look very similar to PowerPivot and contain much of the same functionality.&#160; In fact, both the tabular model and PowerPivot share the same engine &#8230; <a href="http://salvoz.com/blog/2012/01/15/sql-server-2012-tabular-models-vs-powerpivot/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I recently installed SQL Server 2012 and began exploring the tabular models.&nbsp; At first glance, they look very similar to PowerPivot and contain much of the same functionality.&nbsp; In fact, both the tabular model and PowerPivot share the same engine and the DAX language.&nbsp; </p>
<p>Although on the surface they appear very similar, several notable differences exist.</p>
<p>The following grid lists a few of the differences between the tabular model and PowerPivot:</p>
<table border="0" cellspacing="0" cellpadding="2" width="642">
<tbody>
<tr>
<td valign="top" width="191">&nbsp;</td>
<td valign="top" width="220" align="center"><strong>Tabular Model</strong></td>
<td valign="top" width="229" align="center"><strong>PowerPivot</strong></td>
</tr>
<tr>
<td valign="top" width="186"><strong>Scalability</strong></td>
<td valign="top" width="221">
<ul>
<li>No specified upper size limit</li>
<li>Partitions to process large volumes of data</li>
<li>Supports Direct Query and VertiPaq</li>
</ul>
</td>
<td valign="top" width="234">
<ul>
<li>2 GB Excel file size limit (for uploading to SharePoint)</li>
<li>No partitioning</li>
<li>VertiPaq only</li>
</ul>
</td>
</tr>
<tr>
<td valign="top" width="186"><strong>Manageability</strong></td>
<td valign="top" width="221">SSMS, AMO, ADOMD, XMLA, Deployment Wizard, PowerShell, Integration Services<br />(<a href="http://blogs.msdn.com/b/cathyk/archive/2011/09/12/managing-tabular-models.aspx">Cathy Dumas&#8217;s Blog</a>)</td>
<td valign="top" width="234">Excel / SharePoint</td>
</tr>
<tr>
<td valign="top" width="186"><strong>Securability</strong></td>
<td valign="top" width="221">Row level and dynamic security</td>
<td valign="top" width="234">Excel workbook file security</td>
</tr>
<tr>
<td valign="top" width="186"><strong>Development Tool</strong></td>
<td valign="top" width="221">Visual Studio</td>
<td valign="top" width="234">Excel</td>
</tr>
</tbody>
</table>
<p>There are several new features common to both PowerPivot and Tabular Models:</p>
<ul>
<li>Hierarchies</li>
<li>KPIs</li>
<li>Perspectives</li>
</ul>
<p>If you’d like to see a list of the new features in PowerPivot 2012, check out this link (<a title="http://technet.microsoft.com/en-us/library/hh272053(SQL.110).aspx" href="http://technet.microsoft.com/en-us/library/hh272053(SQL.110).aspx">http://technet.microsoft.com/en-us/library/hh272053(SQL.110).aspx</a>).</p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/UlkHctxVxW4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2012/01/15/sql-server-2012-tabular-models-vs-powerpivot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2012/01/15/sql-server-2012-tabular-models-vs-powerpivot/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sql-server-2012-tabular-models-vs-powerpivot</feedburner:origLink></item>
		<item>
		<title>SSIS: Using the Script Component to Obtain an Error Description</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/ZD5YvDp64xI/</link>
		<comments>http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 16:12:00 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/</guid>
		<description><![CDATA[In the SSIS data flow, many data flow components provide an ErrorOutput that allows you to route rows that generate errors or truncation to another component in the data flow.&#160; The ErrorOutput path contains the following metadata: ErrorCode, ErrorColumn and &#8230; <a href="http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the SSIS data flow, many data flow components provide an ErrorOutput that allows you to route rows that generate errors or truncation to another component in the data flow.&nbsp; The ErrorOutput path contains the following metadata: ErrorCode, ErrorColumn and Flat File Source Error Output Column.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML5b0de6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SNAGHTML5b0de6" border="0" alt="SNAGHTML5b0de6" src="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML5b0de6_thumb.png" width="393" height="151"></a></p>
<ul>
<li>Flat File Source Error Output Column &#8211; The data row that generated the error.
<li>ErrorCode &#8211; Code associated with the error that occurred.
<li>ErrorColumn &#8211; Numeric ID of the column that caused the error. </li>
<p><!--EndFragment--></ul>
<p>Obtaining the ErrorDescription requires a bit more work, but can be easily accomplished using the data flow Script Component.</p>
<p>The first step is to add a&nbsp; ‘Script Component’ to your data flow and connect the Error Output as an input to the script component as shown below.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb.png" width="244" height="152"></a></p>
<p>Double click on the script component to edit.</p>
<p>Under the ‘Input Columns’ tab, check the ErrorCode column (you may also include additional columns if you wish to use them in subsequent data flow components).&nbsp; This column is required to obtain the Error Description.&nbsp; The ‘Usage Type’ should be set to ReadOnly.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image1.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb1.png" width="469" height="219"></a></p>
<p>Next, select the ‘Inputs and Outputs’ tab.&nbsp; Expand ‘Output 0’ and select ‘Output Columns’. Click the ‘Add Column’ button.&nbsp; In the ‘Name’ field, enter a descriptive name such as ErrorDescription.&nbsp; Set the DataType field to string [DT_STR] and the length to 255.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML6dd200.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTML6dd200" border="0" alt="SNAGHTML6dd200" src="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML6dd200_thumb.png" width="480" height="382"></a></p>
<p>Click on the ‘Script’ tab and then click the ‘Edit Script’ button.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML6f8e1d.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="SNAGHTML6f8e1d" border="0" alt="SNAGHTML6f8e1d" src="http://salvoz.com/blog/wp-content/uploads/2011/12/SNAGHTML6f8e1d_thumb.png" width="487" height="364"></a></p>
<p>Modify the Input0_ProcessInputRow function (this example uses C#)</p>
<p><font size="2">public override void Input0_ProcessInputRow(Input0Buffer Row)<br /> {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);<br />&nbsp; }</font></p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/ZD5YvDp64xI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssis-using-the-script-component-to-obtain-an-error-description</feedburner:origLink></item>
		<item>
		<title>SSIS: Handling Truncation and Data Errors</title>
		<link>http://feedproxy.google.com/~r/SalvoZ/~3/k5iaUNxNcaA/</link>
		<comments>http://salvoz.com/blog/2011/12/27/ssis-handling-truncation-and-data-errors/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 15:22:00 +0000</pubDate>
		<dc:creator>Jennifer Salvo</dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/2011/12/27/ssis-handling-truncation-and-data-errors/</guid>
		<description><![CDATA[SSIS provides functionality to handle unexpected data in the data flow.&#160; Data flow errors are often due to invalid data values (e.g. string instead of number) and data truncation.&#160; Many components in the data flow support error outputs that allow &#8230; <a href="http://salvoz.com/blog/2011/12/27/ssis-handling-truncation-and-data-errors/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>SSIS provides functionality to handle unexpected data in the data flow.&nbsp; Data flow errors are often due to invalid data values (e.g. string instead of number) and data truncation.&nbsp; </p>
<p>Many components in the data flow support error outputs that allow you to control how truncation and errors are handled.&nbsp; The Error Outputs contain an ErrorCode and ErrorColumn in addition to the data columns in the row that caused the error.&nbsp; Error outputs can be connected to another component in the data flow (e.g. a flat file destination to log the rows that generated errors). </p>
<p>You can control how data errors and truncation are handled:</p>
<p>1. Double click on the Data Flow component.</p>
<p>2. Select ‘Error Output’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb2.png" width="385" height="113"></a></p>
<p>3. In the ‘Error’ and ‘Truncation’ columns, you specify how each scenario should be handled.&nbsp; You may click in any cell to set the value or select multiple cells and then use the drop-down at the bottom of the window to set the value.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb3.png" width="390" height="227"></a></p>
<p>The options are:</p>
<ul>
<li>Ignore Failure &#8211; The row is routed to the&nbsp; ‘Success’ / Default output.
<li>Redirect Row &#8211; The row is routed to the ‘Error’ output.
<li>Fail Component &#8211; The data flow task fails (this is the default option).</li>
</ul>
<p>In the example below, the error output is being routed to a script component.&nbsp; The script component is used to obtain a description of the error based on the error code (<a href="http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/">this blog post provides more details</a>).&nbsp; The errors are then routed to a flat file destination.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image4.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb4.png" width="378" height="184"></a></p>
<p>The ‘Flat File Destination’ is configured so the file is overwritten (so it doesn’t grow uncontrollably).</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb5.png" width="391" height="121"></a></p>
<p>Under the “Mappings” tab, the following columns are written to the file.</p>
<ul>
<li>Flat File Source Error Output Column &#8211; The data row that generated the error.
<li>ErrorCode &#8211; Code associated with the error that occurred.
<li>ErrorColumn &#8211; Numeric ID of the column that caused the error.
<li>ErrorDescription – Description of the error that occurred.&nbsp; The ErrorDescription was obtained in the ‘Script Component’ using the GetErrorDescription function, more details are included in this <a href="http://salvoz.com/blog/2011/12/27/ssis-using-the-script-component-to-obtain-an-error-description/">blog post</a>.</li>
</ul>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2011/12/image6.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2011/12/image_thumb6.png" width="392" height="198"></a></p>
<img src="http://feeds.feedburner.com/~r/SalvoZ/~4/k5iaUNxNcaA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2011/12/27/ssis-handling-truncation-and-data-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://salvoz.com/blog/2011/12/27/ssis-handling-truncation-and-data-errors/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssis-handling-truncation-and-data-errors</feedburner:origLink></item>
	</channel>
</rss>

