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

<channel>
	<title>Salvo(z)</title>
	<atom:link href="http://salvoz.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://salvoz.com/blog</link>
	<description>Aviation, Fitness and Technology</description>
	<lastBuildDate>Sun, 17 Dec 2017 21:29:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.9.1</generator>
	<item>
		<title>Detecting Device Idiom on Xamarin UITest</title>
		<link>http://salvoz.com/blog/2016/08/23/detecting-device-idiom-on-xamarin-uitest/</link>
		<comments>http://salvoz.com/blog/2016/08/23/detecting-device-idiom-on-xamarin-uitest/#respond</comments>
		<pubDate>Tue, 23 Aug 2016 20:01:37 +0000</pubDate>
		<dc:creator><![CDATA[asalvo]]></dc:creator>
				<category><![CDATA[Programming (Other)]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Xamarin]]></category>

		<guid isPermaLink="false">https://salvoz.com/blog/?p=2421</guid>
		<description><![CDATA[When writing UI Tests with Xamarin UITest, you may want to take a different action when testing on a tablet form factor (idiom) or phone. There is some built in support in Xamarin UITest for detecting this on the iOS &#8230; <a href="http://salvoz.com/blog/2016/08/23/detecting-device-idiom-on-xamarin-uitest/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>When writing UI Tests with Xamarin UITest, you may want to take a different action when testing on a tablet form factor (idiom) or phone. There is some built in support in Xamarin UITest for detecting this on the iOS side, but nothing on the Android side. The solution I came up with was to use a <a href="https://developer.xamarin.com/guides/testcloud/uitest/working-with/backdoors/" target="_blank">backdoor</a> method to give me the information I needed. </p>
<p>First, let’s take a look at how we create an instance if IApp, as we will need this for both iOS and Android. I am assuming the user has a basic understanding of how Xamarin UITest works.</p>
<p>When setting up your Test, you will using the FluentAPI built off of ConfigureApp to create an App for either Android or iOS. This creates a platform specific instance that implements IApp.&nbsp; </p>
<p><code>public static IApp StartApp(Platform platform)<br /></code><code>{<br />&nbsp; if (platform == Platform.Android)<br />&nbsp; {<br />&nbsp;&nbsp;&nbsp; return ConfigureApp.Android.DoSomeCustomAndroidConfig.StartApp();<br />&nbsp; }&nbsp; <br />&nbsp; <br />&nbsp; return ConfigureApp.iOS..DoSomeCustomiOSConfig().StartApp();<br />}</code></p>
<p>In my base test class, I call StartApp and then check to see if I’m running on a phone or tablet. </p>
<p><code>[SetUp]<br />public void SetUp()<br />{<br />&nbsp; App = StartApp(Platform);  </p>
<p>&nbsp; <br />&nbsp; //Figure out what kind of Idiom we have. <br />&nbsp; //Use the built in support for iOS and a backdoor method for Android<br />&nbsp; var iOSApp = App as iOSApp;<br />&nbsp; if (iOSApp != null)<br />&nbsp; {<br />&nbsp;&nbsp;&nbsp; IsPhone = iOSApp.Device.IsPhone;<br />&nbsp; }<br />&nbsp; else<br />&nbsp; {<br />&nbsp;&nbsp;&nbsp; var idiom = App.Invoke("BackdoorGetIdiom");<br />&nbsp;&nbsp;&nbsp; IsPhone = idiom.Equals("Phone");<br />}</code>  </p>
<p>We first check to see if our App is of type iOSApp, and if it is, we’ll use the built in support in Xamarin UITest. If we are running on Android, then we’ll use the <a href="https://developer.xamarin.com/guides/testcloud/uitest/working-with/backdoors/" target="_blank">backdoor</a> method approach, which I’ll outline next.</p>
<p>All I had to do was create my backdoor method and expose it from my MainActivity which is in my Xamarin Forms Android project. </p>
<p><code>[Export("BackdoorGetIdiom")]<br />public string BackdoorGetDeviceIdiom()<br />{<br />&nbsp; return Device.Idiom.ToString();<br />}</code>  </p>
<p>You may need to add a reference to the Mono.Android.Export.dll. I found this in “C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v6.0\Mono.Android.Export.dll”. Now, all you need to do is invoke the method as shown in my [SetUp] method. </p>
<p>There are various rules that you must follow when writing your backdoor methods which Xamarin outlines on their <a href="https://developer.xamarin.com/guides/testcloud/uitest/working-with/backdoors/" target="_blank">backdoor documentation page</a>. The rules differ between iOS and Android so be sure to read them carefully. </p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2016/08/23/detecting-device-idiom-on-xamarin-uitest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSMS run as different user</title>
		<link>http://salvoz.com/blog/2015/04/19/ssms-run-as-different-user/</link>
		<comments>http://salvoz.com/blog/2015/04/19/ssms-run-as-different-user/#respond</comments>
		<pubDate>Sun, 19 Apr 2015 19:31:25 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2412</guid>
		<description><![CDATA[runas /netonly /user:&#60;domain&#62;\&#60;username&#62; &#8220;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\ssms.exe&#8221;]]></description>
				<content:encoded><![CDATA[<p>runas /netonly /user:&lt;domain&gt;\&lt;username&gt; &#8220;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\ssms.exe&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/04/19/ssms-run-as-different-user/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rolling X month / X week calculations in MDX using NonEmpty</title>
		<link>http://salvoz.com/blog/2015/04/12/rolling-x-month-x-week-calculations-in-mdx-using-nonempty/</link>
		<comments>http://salvoz.com/blog/2015/04/12/rolling-x-month-x-week-calculations-in-mdx-using-nonempty/#respond</comments>
		<pubDate>Sun, 12 Apr 2015 20:45:20 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[Multidimensional Models]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2410</guid>
		<description><![CDATA[Implementing a rolling x month or x week calculation in MDX is relatively straightforward if you have a calendar hierarchy in the multi-dimensional cube.&#160; In some cases, you may only want to include dates where a measure is non-empty.&#160; For &#8230; <a href="http://salvoz.com/blog/2015/04/12/rolling-x-month-x-week-calculations-in-mdx-using-nonempty/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Implementing a rolling x month or x week calculation in MDX is relatively straightforward if you have a calendar hierarchy in the multi-dimensional cube.&nbsp; In some cases, you may only want to include dates where a measure is non-empty.&nbsp; For example, if a user selects the current month, you may not want to include any future weeks that are empty in the rolling calculation. </p>
<p>Here’s some MDX that implements a rolling 6-week calculation that only includes non-empty dates.</p>
<p>Ancestor(Tail(NonEmpty(Descendants(StrToMember(@Calendar),[Date].[Calendar].[Date]),[Measures].[Registration Count])).Item(0),[Date].[Calendar].[Calendar Week of Year]).Lag(6):Ancestor(Tail(NonEmpty(Descendants(StrToMember(@Calendar),[Date].[Calendar].[Date]),[Measures].[Registration Count])).Item(0),[Date].[Calendar].[Calendar Week of Year])</p>
<p>This implementation uses the DESCENDANTS function to identify all child dates based on the current position in the Calendar hierarchy (represented by the parameter @Calendar).&nbsp; We use the TAIL function to return the last date where the [Registration Count] measure is non-empty; then the ANCESTOR function returns the [Calendar Week of Year] associated to the date returned by the TAIL function.&nbsp; </p>
<p>Once we identify the week based on the current position in the calendar hierarchy we can then use LAG(6) to navigate 6 weeks back.&nbsp; The Range operator ‘:’ returns all the weeks from 6 weeks prior to the current week based on the calendar hierarchy position.</p>
<p>Here’s a complete MDX query using this logic.&nbsp; Note: I’ve replaced StrToMember(@Calendar) with the member [Date].[Calendar].[Calendar Year].&amp;[2015].&amp;[Q2 2015].&amp;[Apr 2015].</p>
<p>SELECT {[Measures].[Registration Count]} ON COLUMNS,&nbsp; NON EMPTY [Date].[Calendar Week of Year].[Calendar Week of Year].MEMBERS ON ROWS<br />FROM [Cube]<br />WHERE Ancestor(Tail(NonEmpty(DESCENDANTS([Date].[Calendar].[Calendar Year].&amp;[2015].&amp;[Q2 2015].&amp;[Apr 2015],[Date].[Calendar].[Date]),[Measures].[Registration Count])).ITEM(0),[Date].[Calendar].[Calendar Week of Year]).LAG(6):Ancestor(Tail(NonEmpty(DESCENDANTS([Date].[Calendar].[Calendar Year].&amp;[2015].&amp;[Q2 2015].&amp;[Apr 2015],[Date].[Calendar].[Date]),[Measures].[Registration Count])).ITEM(0),[Date].[Calendar].[Calendar Week of Year])</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/04/12/rolling-x-month-x-week-calculations-in-mdx-using-nonempty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rolling X months / X weeks calculations in DAX</title>
		<link>http://salvoz.com/blog/2015/04/12/rolling-x-months-x-weeks-calculations-in-dax/</link>
		<comments>http://salvoz.com/blog/2015/04/12/rolling-x-months-x-weeks-calculations-in-dax/#comments</comments>
		<pubDate>Sun, 12 Apr 2015 19:56:47 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[DAX]]></category>
		<category><![CDATA[SSAS]]></category>
		<category><![CDATA[Tabular Models]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2408</guid>
		<description><![CDATA[I recently implemented rolling 12 month and rolling 6 week measures in a SSAS tabular cube for product registration counts. The rolling 12 month calculation is straight-forward and can be implemented using built-in DAX formulas.&#160; This implementation is based off &#8230; <a href="http://salvoz.com/blog/2015/04/12/rolling-x-months-x-weeks-calculations-in-dax/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I recently implemented rolling 12 month and rolling 6 week measures in a SSAS tabular cube for product registration counts.</p>
<p>The rolling 12 month calculation is straight-forward and can be implemented using built-in DAX formulas.&nbsp; This implementation is based off of Alberto Ferrari’s blog post. <a title="http://www.sqlbi.com/articles/rolling-12-months-average-in-dax/" href="http://www.sqlbi.com/articles/rolling-12-months-average-in-dax/">http://www.sqlbi.com/articles/rolling-12-months-average-in-dax/</a>.</p>
<p>Registration Count Rolling 12 Mos:=CALCULATE([Registration Count Current Period], DATESBETWEEN(&#8216;Date'[Date], SAMEPERIODLASTYEAR(NEXTDAY(LASTDATE(&#8216;Date'[Date]))),LASTDATE(&#8216;Date'[Date])))</p>
<p>The LASTDATE function returns the last date contained within the active filter context of the cube.&nbsp; For example, if a user has filtered to July 2015 then last date will return July 31, 2015 based on a standard calendar implementation.&nbsp; The function SAMEPERIODLASTYEAR is using the day after the last date in our filtered dataset and identifies the same date in the prior year.&nbsp; DATESBETWEEN then identifies all the dates between last year’s and this year’s date.</p>
<p>The rolling 6 weeks implementation was less straightforward. I ended up implementing this calculation using a combination of a calculated column and measure in the cube.</p>
<p>First, I added a column called ‘ThisSaturday’ to the Date table in the cube.&nbsp; For each date in the Date table, it calculates Saturday’s date in the same week.</p>
<p>The calculated column formula is listed below:</p>
<p>=CALCULATE(MIN(&#8216;Date'[Date]), FILTER(ALL(&#8216;Date&#8217;),&#8217;Date'[Day of Week]=7 &amp;&amp; &#8216;Date'[Date] &gt;= EARLIER(&#8216;Date'[Date])))</p>
<p>We’re basically using the FILTER function to retrieve all the Saturday’s that are on or after the present date and then the MIN function identifies the Saturday that is nearest to the date.</p>
<p>Once we have this calculated column added to the date table, we can then apply it in our rolling 6 week measure.</p>
<p>Registration Count Rolling 6 Wks:=CALCULATE([Registration Count Current Period], DATESBETWEEN(&#8216;Date'[Date], LASTDATE(&#8216;Date'[ThisSaturday])-41,LASTDATE(&#8216;Date'[ThisSaturday])))</p>
<p>In this measure, we use LASTDATE to identify the last date associated to the current filter context.&nbsp; We then subtract 41 to calculate the date 6-weeks prior and use DATESBETWEEN to retrieve all the dates between this date and the Saturday of the last date in the filter context.&nbsp; </p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/04/12/rolling-x-months-x-weeks-calculations-in-dax/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SSAS Tabular Custom Prior Year Date Calculations</title>
		<link>http://salvoz.com/blog/2015/02/15/ssas-tabular-custom-prior-year-date-calculations/</link>
		<comments>http://salvoz.com/blog/2015/02/15/ssas-tabular-custom-prior-year-date-calculations/#respond</comments>
		<pubDate>Sun, 15 Feb 2015 21:26:13 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[DAX]]></category>
		<category><![CDATA[SSAS]]></category>
		<category><![CDATA[Tabular Models]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2400</guid>
		<description><![CDATA[I am working on building a tabular cube and needed the ability to compare current fiscal year dates to prior fiscal year dates by matching the dates based on the same fiscal month and day of month and then performing &#8230; <a href="http://salvoz.com/blog/2015/02/15/ssas-tabular-custom-prior-year-date-calculations/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I am working on building a tabular cube and needed the ability to compare current fiscal year dates to prior fiscal year dates by matching the dates based on the same fiscal month and day of month and then performing calculations to compare sales between the current and prior fiscal year.&nbsp; The built-in DAX date calculations didn’t appear to meet my needs (at least I wasn’t able to obtain the desired results using them), so I implemented the necessary behavior using an inactive relationship from my date dimension to the sales fact table.</p>
<p>As a first step, I added two additional columns to my tabular cube date dimensions that represents the prior year date key and date.&nbsp; An example of the query is included below (note: for simplicity in this blog post I have not included all the date dimension attributes, an actual date dimension would likely have many more attributes than what I have included).&nbsp; One challenge I encountered is an occasional mismatch between the number of days in a given fiscal month when comparing two fiscal years (some fiscal years have more days in a particular fiscal month than the prior year);&nbsp; therefore, I am using a LEFT OUTER JOIN and then ISNULL to return an unknown for the LastYearDateKey column.&nbsp; In addition, this column needs to have a unique value so the unknown is set to be –1 multiplied by the prior year date key.</p>
<p>SELECT DateKey, [Date], ISNULL(c.LastYearDateKey,-1*DateKey) [LastYearDateKey],c.LastYearDate [LastYearDate]<br />FROM DimDate d<br />LEFT OUTER JOIN (<br />&nbsp;&nbsp;&nbsp; SELECT c.DateKey CurrentYearDateKey<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,l.DateKey LastYearDateKey<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,l.Date LastYearDate<br />&nbsp;&nbsp;&nbsp; FROM DimDate l<br />&nbsp;&nbsp;&nbsp; INNER JOIN (SELECT DateKey,Date,FiscalYear &#8211; 1 [FiscalYear],FiscalMonth,FiscalDayOfMonth FROM DimDate) c ON l.FiscalYear = c.FiscalYear <br />&nbsp;&nbsp;&nbsp; AND l.FiscalMonth = c.FiscalMonth <br />&nbsp;&nbsp;&nbsp; AND l.FiscalDayOfMonth = c.FiscalDayOfMonth) c ON d.DateKey = c.CurrentYearDateKey </p>
<p>Now that I have the necessary columns added to my dimension, I created an inactive relationship from my sales fact table to the new LastYearDateKey column in the date dimension (The primary / active relationship from the date table to the sales fact table is based on the current year date key).&nbsp; The following shows the inactive relationship between the two tables (note that the active checkbox is unchecked). </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/02/image.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/02/image_thumb.png" width="550" height="268"></a>  </p>
<p>With the inactive relationship established, I can create measures using DAX calculations that reference this inactive relationship.</p>
<p>Here’s an example of a measure in my sales table that uses the inactive relationship:</p>
<p>Sales Amount PY:=CALCULATE(SUM([SalesAmount]),USERELATIONSHIP(Dates[LastYearDateKey],Sales[GLDateKey])).</p>
<p>Now, I can compare sales in the prior year to the current year using the custom date matching (based on fiscal month and day of month) defined in my date dimension query.</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/02/15/ssas-tabular-custom-prior-year-date-calculations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BCP of large dataset to SQL DB on Azure Virtual Machine</title>
		<link>http://salvoz.com/blog/2015/02/15/bcp-of-large-dataset-to-sql-db-on-azure-virtual-machine/</link>
		<comments>http://salvoz.com/blog/2015/02/15/bcp-of-large-dataset-to-sql-db-on-azure-virtual-machine/#respond</comments>
		<pubDate>Sun, 15 Feb 2015 19:37:04 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2395</guid>
		<description><![CDATA[During the past 6 months, I’ve been working on re-designing an app that uses BCP to move data from thousands of similar (but not identical) databases each storing sales and other related data for individual bicycle dealers into a unified &#8230; <a href="http://salvoz.com/blog/2015/02/15/bcp-of-large-dataset-to-sql-db-on-azure-virtual-machine/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>During the past 6 months, I’ve been working on re-designing an app that uses BCP to move data from thousands of similar (but not identical) databases each storing sales and other related data for individual bicycle dealers into a unified database on an Azure Virtual Machine (currently a D13 VM with 8 core, 56 GB and SSD) that stores the data for all dealers.&nbsp; The overall unified database is roughly 500 GB in size and is reloaded on a weekly basis, so the movement and loading of data needed to be optimized as much as possible. </p>
<p>Originally this process was implemented via Powershell scripts using BCP, file compression (.zip) and FTP.&nbsp; The data was first BCP’d from tables in the dealer’s database into a flat file format.&nbsp; Then the dealer’s flat files were compressed into .zip format and FTP’d.&nbsp; Another set of Powershell scripts ran on the receiving server (in Azure) and pulled the files down via FTP, unzipped them and executed BCP commands to move the data from the flat file into the database.&nbsp; The scripts processed one table at a time for a single dealer and once all tables completed it would move onto the next dealer in the queue.&nbsp; Overall, the total dataset was taking roughly 15-16 hours to load and was unsustainable.</p>
<p>To optimize the process further, the Powershell scripts were replaced with a C# application.&nbsp; The C# application is multi-threaded to load multiple tables in parallel as well as multiple dealers, the number of dealers that can be loaded in parallel is controlled by a parameter.&nbsp; After performing some benchmark testing, the parameter was set to 10 parallel locations since this appears to provide the best performance.&nbsp; The C# application uses the SqlBulkCopyService which directly BCPs data from tables in the dealer’s database to the appropriate tables in the unified database residing in Azure.&nbsp; This eliminated the flat files and the need to compress and FTP them.&nbsp; The C# application’s performance provided a significant improvement, the data is now loading in roughly 9 hours versus 15-16 hours with the Powershell scripts, thanks in large part to the parallel loading of tables and dealers.</p>
<p>In addition to re-working the code to move the data, several optimizations were also implemented involving the unified database and virtual machine in Azure.&nbsp; During initial performance testing while BCP’ing the data, the unified database log file was a bottleneck.&nbsp; The log file was originally on a persistent VHD stored on Azure blog storage.&nbsp; To improve log performance, the log file is temporarily moved to the D: drive (local non-persistent SSD drive) throughout the duration of the weekly load. Once the load completes, the log file is moved back to a persistent drive.&nbsp; We also have the database data file on a drive spread across 10 disks to help improve the IO performance and to allow for future growth.&nbsp; The index file is split across two disks for performance as well.</p>
<p>I’m sure this implementation will continue to evolve over time and I will write more blog posts as things progress.</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/02/15/bcp-of-large-dataset-to-sql-db-on-azure-virtual-machine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Log4Net Nuget Package in SSIS</title>
		<link>http://salvoz.com/blog/2015/01/19/using-log4net-in-ssis/</link>
		<comments>http://salvoz.com/blog/2015/01/19/using-log4net-in-ssis/#respond</comments>
		<pubDate>Mon, 19 Jan 2015 16:46:27 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[Programming (Other)]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[log4net]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2392</guid>
		<description><![CDATA[Log4Net is a robust logging framework that provides programmers granular control over logging to a variety of target outputs (examples include file, console, email, etc.).&#160; Detailed documentation can be found on the Apache Log4Net site. It is possible to use &#8230; <a href="http://salvoz.com/blog/2015/01/19/using-log4net-in-ssis/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Log4Net is a robust logging framework that provides programmers granular control over logging to a variety of target outputs (examples include file, console, email, etc.).&nbsp; Detailed documentation can be found on the Apache Log4Net <a href="http://logging.apache.org/log4net/">site</a>.</p>
<p>It is possible to use Log4Net within SSIS script tasks/components, but the implementation is a bit different than when used within console or web applications.&nbsp; </p>
<p>1.&nbsp; Create or open an SSIS script task or component.&nbsp; Click ‘Edit Script’.</p>
<p>2.&nbsp; In the Solution Explorer window, right click on the solution and select ‘Manage NuGet Packages’.&nbsp; </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb.png" width="244" height="141"></a> </p>
<p>If you do not see the option ‘Manage NuGet Packages’, then you will need to install the package manager extension.&nbsp; This can be done from within Visual Studio.</p>
<p>Go to Tools &gt; Extension Manager.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image1.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb1.png" width="244" height="157"></a> </p>
<p>Search the online gallery for ‘NuGet Package Manager’ and install.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image2.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb2.png" width="439" height="136"></a> </p>
<p>3.&nbsp; In the ‘Nuget Package Manager’ window, click ‘Online’ in the left navigation pane and then search for Log4Net.&nbsp; Click ‘Install’ and then Close.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image3.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb3.png" width="426" height="139"></a> </p>
<p>You should now see a Packages.config file added to your project.&nbsp; The Packages.config file stores the version information for the nuget package(s) installed.&nbsp; The following is an example:</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image4.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb4.png" width="523" height="156"></a> </p>
</p>
<p>When a package is restored, Nuget references the Packages.config file to pull down the correct version of the package (in this case version 2.0.3).</p>
<p>4.&nbsp; In addition to adding the package via Nuget within the SSIS script task, the Log4Net.dll file will also need to be added to the GAC.&nbsp; There are several ways to add a dll to the GAC, Powershell is one option:</p>
<p>Set-location &#8220;c:\temp&#8221; </p>
<p>[System.Reflection.Assembly]::Load(&#8220;System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&#8221;) </p>
<p>$publish = New-Object System.EnterpriseServices.Internal.Publish </p>
<p>$publish.GacInstall(&#8220;c:\temp\log4net.dll&#8221;) </p>
<p><em>Reference:</em> <a title="http://social.technet.microsoft.com/wiki/contents/articles/22618.how-to-install-a-dll-to-the-gac-on-windows-server-2012-using-only-powershell.aspx" href="http://social.technet.microsoft.com/wiki/contents/articles/22618.how-to-install-a-dll-to-the-gac-on-windows-server-2012-using-only-powershell.aspx">http://social.technet.microsoft.com/wiki/contents/articles/22618.how-to-install-a-dll-to-the-gac-on-windows-server-2012-using-only-powershell.aspx</a> </p>
<p>5.&nbsp; Now we have reached the point where we can start writing some code.&nbsp; Generally, all Log4Net configurations are set in the App.config file or a custom Log4Net config file.&nbsp;&nbsp; </p>
<p>Since the DTEXEC.EXE application runs the SSIS packages, it is not possible to directly associate config files to the package script task/component.&nbsp; Therefore, all Log4Net configuration settings must be set programmatically. </p>
<p>I used the following StackOverflow post as a reference: <a title="http://stackoverflow.com/questions/2738130/using-log4net-as-a-logging-mechanism-for-ssis" href="http://stackoverflow.com/questions/2738130/using-log4net-as-a-logging-mechanism-for-ssis">http://stackoverflow.com/questions/2738130/using-log4net-as-a-logging-mechanism-for-ssis</a> </p>
<p>First, add the following log4net references to the Namespaces </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image5.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb5.png" width="244" height="108"></a>  </p>
<p>Now add a new member of type log4net.ILog to the Script class </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image6.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb6.png" width="550" height="193"></a>  </p>
<p>Create a new method called InitLogger </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image7.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb7.png" width="550" height="354"></a>  </p>
<p>Now add some logging to your main method.&nbsp; In this example all levels of severity are being logged to the file h:\\ssis\TestLog_{Timestamp}.log </p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2015/01/image8.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2015/01/image_thumb8.png" width="549" height="196"></a>  </p>
<p>the line of code logger.Info(“Test Log Message”) writes a single line of output to the logging file.  </p>
<p>You can adjust the severity level by calling the appropriate method.&nbsp; This is a code sample from <a href="http://www.beefycode.com/post/Log4Net-Tutorial-pt-1-Getting-Started.aspx">www.beefycode.com</a> </p>
<p><code>logger.Debug( </code><code>"Hello World!"</code> <code>);</code> </p>
<p><code></code><code>logger.Info( </code><code>"I'm a simple log4net tutorial."</code> <code>);</code> </p>
<p><code></code><code>logger.Warn( </code><code>"... better be careful ..."</code> <code>);</code> </p>
<p><code></code><code>logger.Error( </code><code>"ruh-roh: an error occurred"</code> <code>);</code> </p>
<p><code></code><code>logger.Fatal( </code><code>"OMG we're dooooooomed!"</code> <code>);</code> </p>
<p>There are a few other nuances to be aware of.&nbsp; When you close and re-open your SSIS project, you will need to restore the Log4Net Nuget package in the script task/component.&nbsp; To accomplish this, simply re-open the Nuget Package Manager.&nbsp; You will see a message stating <em>‘Some NuGet packages are missing from this solution.&nbsp; Click to restore from your online package sources’</em>.&nbsp; Click ‘Restore’ in the upper right corner.&nbsp; The Nuget Package Manager will restore the same version of the package referenced in the Packages.config file.&nbsp; </p>
<p>If you want to Update to a newer version of the package, click the ‘Updates’ option in the left navigation pane.&nbsp; All available updates should be displayed.</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2015/01/19/using-log4net-in-ssis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Azure VM Local Disk Performance</title>
		<link>http://salvoz.com/blog/2014/11/23/azure-vm-local-disk-performance/</link>
		<comments>http://salvoz.com/blog/2014/11/23/azure-vm-local-disk-performance/#respond</comments>
		<pubDate>Mon, 24 Nov 2014 02:04:03 +0000</pubDate>
		<dc:creator><![CDATA[asalvo]]></dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Azure]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2371</guid>
		<description><![CDATA[Azure Virtual Machines, have always had a local non-persistent disk attached to them, with the size of this disk varies with the size of the VM. In the lead up to the release of the D-Series VMs, the performance of &#8230; <a href="http://salvoz.com/blog/2014/11/23/azure-vm-local-disk-performance/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Azure Virtual Machines, have always had a local non-persistent disk attached to them, with the size of this disk varies with the size of the VM. In the lead up to the release of the D-Series VMs, the performance of the local disk on the original A-Series has been, in my opinion throttled in order for the D-Series to be marketed more effectively. In the graph below, you can see my personal IOPs benchmarks for the Azure local disk. Performance steadily increased, before dropping off sharply this fall with the D-Series showing the same performance which was once available on the A-Series.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2014/11/AzureVMDiskPerformance.png"><img class="alignnone size-medium wp-image-2372" alt="AzureVMDiskPerformance" src="http://salvoz.com/blog/wp-content/uploads/2014/11/AzureVMDiskPerformance-300x176.png" width="300" height="176" srcset="http://salvoz.com/blog/wp-content/uploads/2014/11/AzureVMDiskPerformance-300x176.png 300w, http://salvoz.com/blog/wp-content/uploads/2014/11/AzureVMDiskPerformance-500x294.png 500w, http://salvoz.com/blog/wp-content/uploads/2014/11/AzureVMDiskPerformance.png 963w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>&nbsp;</p>
<p>It&#8217;s unfortunate that the A-Series had to suffer this drop in performance, but it&#8217;s not too bad when you look at the pricing.</p>
<p><a href="http://azure.microsoft.com/en-us/pricing/calculator/?scenario=virtual-machines">Azure Retail Pricing for Standard VMs</a>:</p>
<p>D11 (2 cores, 14GB ram, 100GB SSD): $0.366/hr, $272.31/month<br />
A5 (2 cores, 14GB ram): $0.30/hr, $223.20/month</p>
<p>D13(8 cores, 56 GB ram, 400 GB SSD): $1.318/hr, $980.60/month<br />
A7 (8 cores, 56 GB ram): $1.20/hr, $892.80/month</p>
<p>In addition to the SSD on the D-Series, you also get 60% faster CPU over the A-Series.</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2014/11/23/azure-vm-local-disk-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing .Net 3.5 on Server 2012R2 Azure VMs</title>
		<link>http://salvoz.com/blog/2014/11/06/installing-net-3-5-on-server-2012r2-azure-vms/</link>
		<comments>http://salvoz.com/blog/2014/11/06/installing-net-3-5-on-server-2012r2-azure-vms/#respond</comments>
		<pubDate>Thu, 06 Nov 2014 17:36:34 +0000</pubDate>
		<dc:creator><![CDATA[asalvo]]></dc:creator>
				<category><![CDATA[IT]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2368</guid>
		<description><![CDATA[There are several blog posts, technet articles and Server Fault posts about installing .net 3.5 on Windows 8 and Server 2012/R2. The gist of it, is that you use the command line tool dism, with the /Source switch to specify &#8230; <a href="http://salvoz.com/blog/2014/11/06/installing-net-3-5-on-server-2012r2-azure-vms/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>There are several blog posts, technet articles and Server Fault posts about installing .net 3.5 on Windows 8 and Server 2012/R2. The gist of it, is that you use the command line tool dism, with the /Source switch to specify the path to the SXS folder from the installation media used. Here is an example of the dism command:</p>
<p>dism.exe /online /enable-feature /featurename:NetFx3 /norestart /LimitAccess /Source:&#8221;\\FilleServer\Software\WindowsUpdates\Server2012R2-Update-SXS&#8221; /All</p>
<p>I have run into a couple of issues when running this on Azure VMs created using the latest versions of the Windows 2012 R2 Datacenter gallery image which I wanted to share.</p>
<p>1) The install media change between RTM and Update 1.</p>
<p>When this happened, I had to download the ISO that had update 1 slipstreamed an extract the SXS folder. You&#8217;ll notice in my example command above, the path contains \Server2012R2-Update-SXS. I have a corresponding folder that has the RTM bits.</p>
<p>2) Security Updates <a title="https://support.microsoft.com/kb/2966827" href="https://support.microsoft.com/kb/2966827">2966827</a> or <a title="https://support.microsoft.com/kb/2966828" href="https://support.microsoft.com/kb/2966828">2966828</a>, fixed by <a title="https://support.microsoft.com/kb/3005628" href="https://support.microsoft.com/kb/3005628">3005628</a>.</p>
<p>The two security updates, 2966827 and 2966828, broke the ability to install .Net 3.5. Those two updates have been fixed so that they are only installed if .Net 3.5 has already been installed. Update 3005628 can be used to fix the issues if you have already installed one of the two problem updates, as was the case with the latest Azure gallery image.</p>
<p>I ended up using the MSU package (<a title="http://go.microsoft.com/fwlink/?linkid=517245&amp;clcid=0x409" href="http://go.microsoft.com/fwlink/?LinkID=517245&amp;clcid=0x409">Download the Windows8.1-KB2966828-x64.msu package now)</a>, as I figured that the gallery images met the criteria: &#8220;Customers who are aware that the DISM <a title="http://technet.microsoft.com/en-us/library/hh825265.aspx" href="http://technet.microsoft.com/en-us/library/hh825265.aspx">&#8220;/StartComponentCleanup&#8221; and &#8220;/ResetBase&#8221;</a> option was used on their system&#8230;&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2014/11/06/installing-net-3-5-on-server-2012r2-azure-vms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connect to SharePoint Online List via CSOM in SSIS</title>
		<link>http://salvoz.com/blog/2014/05/23/connect-to-sharepoint-online-list-via-csom-in-ssis/</link>
		<comments>http://salvoz.com/blog/2014/05/23/connect-to-sharepoint-online-list-via-csom-in-ssis/#respond</comments>
		<pubDate>Fri, 23 May 2014 15:22:10 +0000</pubDate>
		<dc:creator><![CDATA[jsalvo]]></dc:creator>
				<category><![CDATA[Database and BI]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SSIS]]></category>

		<guid isPermaLink="false">http://salvoz.com/blog/?p=2358</guid>
		<description><![CDATA[Retrieving data from a list in SharePoint Online requires a slightly different implementation than SharePoint on-prem.&#160; The following example uses C# and CSOM to retrieve data from a SharePoint Online list in an SSIS dataflow script component.&#160; 1.&#160; First you’ll &#8230; <a href="http://salvoz.com/blog/2014/05/23/connect-to-sharepoint-online-list-via-csom-in-ssis/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Retrieving data from a list in SharePoint Online requires a slightly different implementation than SharePoint on-prem.&nbsp; The following example uses C# and CSOM to retrieve data from a SharePoint Online list in an SSIS dataflow script component.&nbsp; </p>
<p>1.&nbsp; First you’ll need to add two references to the SSIS Script Component Visual Studio project.&nbsp; To add a reference right click references and select ‘Add Reference’.</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2014/05/image.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2014/05/image_thumb.png" width="244" height="116"></a> </p>
<p>Click the .NET tab and then add the following two reference to your project: </p>
<ul>
<li>Microsoft.SharePoint.Client</li>
<li>Microsoft.SharePoint.Client.Runtime</li>
</ul>
<p>2.&nbsp; Update the Namespaces region so it is similar to the following:</p>
<blockquote>
<p>#region Namespaces<br />using System;<br />using System.Data;<br />using Microsoft.SqlServer.Dts.Pipeline.Wrapper;<br />using Microsoft.SqlServer.Dts.Runtime.Wrapper;<br />using Microsoft.SharePoint;<br />using Microsoft.SharePoint.Client;<br />using System.Security;<br />#endregion</p>
</blockquote>
<p><strong>Note:</strong> most of the namespaces are already included by default, the bottom three were added for this implementation.</p>
<p>3.&nbsp; Add the following variables to the class definition:</p>
<ul>
<li>private SecureString secureStr;</li>
<li>private ClientContext cc;</li>
<li>private List spList;</li>
<li>private String query = &#8220;&lt;View&gt;&lt;Query&gt;&lt;OrderBy&gt;&lt;FieldRef Name=&#8217;ID&#8217;/&gt;&lt;/OrderBy&gt;&lt;/Query&gt;&lt;/View&gt;&#8221;;</li>
</ul>
<p>The query variable stores the Caml query that will be used to retrieve all fields for all items in the list and sorts them by ID.&nbsp; More information regarding Caml can be found <a href="http://sharepoint-works.blogspot.com/2012/05/caml-query-tutorial-for-sharepoint.html">here</a>.</p>
<p>3.&nbsp; When connecting to a list in SharePoint Online, you need to use the class SharePointOnlineCredentials to set the user and password credentials.&nbsp; The Client Context class is used to establish a connection to SharePoint.&nbsp; The following code is from the method called CreateNewOutputRows().</p>
<p><a href="http://salvoz.com/blog/wp-content/uploads/2014/05/image1.png"><img title="image" style="border-top: 0px;border-right: 0px;border-bottom: 0px;border-left: 0px" border="0" alt="image" src="http://salvoz.com/blog/wp-content/uploads/2014/05/image_thumb1.png" width="550" height="387"></a> </p>
<p><strong>Some helpful notes:</strong></p>
<ul>
<li>Variable.SharepointURL is a URL to the SharePoint site collection where the list resides.&nbsp; Something similar to https://&lt;SharePoint Instance&gt;/sites/&lt;site name&gt;.</li>
<li>The name of the SharePoint list being referenced is “Benchmark Category”. </li>
<li>The SecureString class must be used for SharePoint Online Credentials.&nbsp; cc.Credentials = new SharePointOnlineCredentials(User.SharePointUser, secureStr).</li>
<li>When iterating through the items in the list, I am referencing each item based on the key associated to the list field.&nbsp; In the SharePoint list we have a field with the name ‘Product Category’, but the key associated to that field is ‘Title’; therefore, I am referencing this field using item[“Title”].&nbsp; We also have a field that is displayed as ‘Benchmark Category’ and the key for this field is ‘Benchmark_x0020_Category’.</li>
<li>The ‘Benchmark Category’ field is defined as type ‘Choice’ in SharePoint (users can select from a list of items in a drop-down); therefore, I needed to cast item[“Benchmark_x0020_Category”] to a String array and then retrieve the item at the first index (0).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://salvoz.com/blog/2014/05/23/connect-to-sharepoint-online-list-via-csom-in-ssis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
