<?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>C# City</title>
	<atom:link href="http://www.csharpcity.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.csharpcity.com</link>
	<description>C# Articles, Tutorials, and Reusable Code</description>
	<lastBuildDate>Mon, 14 May 2012 17:54:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Simple Strategies to Boost SQL Server Performance</title>
		<link>http://www.csharpcity.com/simple-strategies-to-boost-sql-server-performance/</link>
		<comments>http://www.csharpcity.com/simple-strategies-to-boost-sql-server-performance/#comments</comments>
		<pubDate>Mon, 14 May 2012 17:54:02 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Platform]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Topic]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=443</guid>
		<description><![CDATA[SQL Server can be a beast on your disk. Two easy ways to help raise performance for high-volume databases: Use a drive other than the Windows partition for the SQL Server DB files, and split the MDF and LDF files onto different drives if possible. <a href="http://www.csharpcity.com/simple-strategies-to-boost-sql-server-performance/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>SQL Server is quite the beast. It eats most of your available RAM. And, with a high-volume database, it can also gobble up your IO, leaving your disk with a long queue.</p>
<p>Disk Queue Length, incidentally, is something you can see in Windows 7+, under the Resource Monitor (Start > Task Manager > Performance tab > Resource Monitor > Disk tab)</p>
<p><img src="http://www.csharpcity.com/wp-content/uploads/2012/05/disk-queue-length.png" alt="" title="disk-queue-length" width="800" height="600" class="alignnone size-full wp-image-444" /></p>
<p>Anyway, during large inserts, or imports, or selects, you may see your disk queue length spike up. This means that your computer is requesting data from the disk, but it&#8217;s busy spinning and getting data for different requests; so they start to rack up.</p>
<p>If you see a queue length of, say, 50, that means you have some heavy IO that&#8217;s sucking up all your disk availability and queueing up tons of requests &#8212; like when you&#8217;re restoring an 8GB database into SQL Server (please, use Attach next time.)</p>
<p>Two easy ways to increase performance in this case:</p>
<ol>
<li><strong>Not the Windows Partition:</strong> By default, SQL Server installs to C:\, the same place as Windows. <em>Move the data files off of the Windows drive.</em> You will immediately see an (often drastic) drop in queue length. Why? Because Windows makes a lot of requests, and if they start to queue up, it can make the queue much longer. If you have a second (physical, not logical) hard drive, that&#8217;s an ideal place to locate the files.</li>
<li><strong>Split MDF and LDF Drives:</strong> Ideally, if you have three or more drives, you should put Windows on one, your MDFs on a second, and your LDFs on a third for maximum performance.</li>
</ol>
<p>Again, unless you see the specific problem of disk queue length, you might not need to do all this. Plus, memory is usually a heavier bottleneck for SQL Server, not disk &#8212; so check that first.</p>
<p>How can you set the location of the MDF and LDF files? With new databases, when creating them, SQL Server shows you &#8220;Database Files&#8221; listed under &#8220;General,&#8221; with a &#8220;Path&#8221; property. Just change it to something else.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/simple-strategies-to-boost-sql-server-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Storing a String List in App.Config or Web.Config</title>
		<link>http://www.csharpcity.com/storing-a-string-list-in-app-config-or-web-config/</link>
		<comments>http://www.csharpcity.com/storing-a-string-list-in-app-config-or-web-config/#comments</comments>
		<pubDate>Thu, 10 May 2012 21:38:23 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Core .NET]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[app.config]]></category>
		<category><![CDATA[web.config]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=441</guid>
		<description><![CDATA[How can you store a list of strings (or ints, say) into a single appSetting key/value pair? Surprisingly, it's as easy as using a delimited list (like comma-delimited or semicolon-delimited) and splitting it at runtime. <a href="http://www.csharpcity.com/storing-a-string-list-in-app-config-or-web-config/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>App.Config and Web.Config allow you to easily store configuration for use at runtime. The facility they expose is key/value pairs, like so:</p>
<p><pre><code>
&lt;appSettings&gt;
&nbsp;&nbsp;&lt;add key=&quot;drive&quot; value=&quot;C:\&quot; /&gt;
&lt;/appsettings&gt;
</code></pre></p>
<p>At runtime, you can access these values like so:</p>
<p><pre><code>
System.Configuration.ConfigurationManager.AppSettings[&quot;drive&quot;]; // returns &quot;C:\&quot;
</code></pre></p>
<p>This is great for storing a few key/value pairs for different uses. But what if you wanted to store a list of strings? In our example, what if you wanted to store multiple drives? How can you do this?</p>
<p>One solution is to use multiple key/value pairs, like so:</p>
<p><pre><code>
&lt;appSettings&gt;
&nbsp;&nbsp;&lt;add key=&quot;drive1&quot; value=&quot;C:\&quot; /&gt;
&nbsp;&nbsp;&lt;add key=&quot;drive2&quot; value=&quot;D:\&quot; /&gt;
&lt;/appsettings&gt;
</code></pre></p>
<p>Of course, this means you have to individually access the values at runtime; you can&#8217;t just grab them all into a single array or string.</p>
<p>The answer is surprisingly easy: just <strong>store the value as a delimited list and split it at runtime,</strong> like so:</p>
<p><pre><code>
&lt;appSettings&gt;
&nbsp;&nbsp;&lt;add key=&quot;drives&quot; value=&quot;C:, D:&quot; /&gt;
&lt;/appsettings&gt;
</code></pre></p>
<p>And at runtime:</p>
<p><pre><code>
string[] drives = ConfigurationManager.AppSettings[&quot;drives&quot;].Split(&#039;,&#039;).Select(s =&gt; s.Trim()).ToArray();
</code></pre></p>
<p>(The <code>Select</code> and <code>Trim</code> calls allow us to use white-spaces in the config file, and get a trimmed, whitespace-free list of drives.) This code would return, as expected, a string array:</p>
<p><pre><code>
drives[0] = &quot;C:&quot;
drives[1] = &quot;D:&quot;
</code></pre></p>
<p>Easy, right? But not so obvious. In fact, the obvious answer to this is <strong>to use a custom section</strong>. Personally, I feel that this is overkill for  asimple list of strings, ints, or other basic types. (Technically, you can shove any serializable class in here; as long as you have a non-ambiguous delimiter, you&#8217;re good.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/storing-a-string-list-in-app-config-or-web-config/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Procedure Expects Parameter Which Was Not Supplied</title>
		<link>http://www.csharpcity.com/procedure-expects-parameter-which-was-not-supplied/</link>
		<comments>http://www.csharpcity.com/procedure-expects-parameter-which-was-not-supplied/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 19:40:42 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Core .NET]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[null]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[System.Data]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=439</guid>
		<description><![CDATA[SqlCommand's Parameters prevent SQL injection attacks. Surprisingly, when passed in a null value, you get the exception: Procedure or function "..." expects parameter '@foo', which was not supplied. <a href="http://www.csharpcity.com/procedure-expects-parameter-which-was-not-supplied/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>SQL parameters are awesome. They automatically protect you from SQL injection attacks. They do have one strange caveat, though: <strong>you cannot pass a null value to a SQL parameter.</strong> Doing so will give you this interesting and unhelpful exception:</p>
<p><code>Procedure or function &quot;...&quot; expects parameter &#039;@foo&#039;, which was not supplied</code></p>
<p>This doesn&#8217;t make sense when you have code like:</p>
<p><pre><code>
string foo = getSomeFoo(); // May return null
SqlCommand cmd = new SqlCommand(&quot;SELECT * FROM someTable WHERE foo = @foo&quot;);
cmd.Parameters.AddWithValue(&quot;@foo&quot;, foo);
cmd.ExecuteNonQuery(); // Throws exception
</code></pre></p>
<p>You can see that <code>@foo</code> is, indeed, supplied. But in the case where the value is null, you will see an exception.</p>
<p>So what&#8217;s the solution? You can make sure that <code>foo</code> has a value, or some non-null value (like empty string or <code>DBNull.Value</code>), or you can conditionally add the parameter when needed.</p>
<p>And calling a stored procedure with a parameter that may be null? That, my friends, is <a href="https://www.google.ca/webhp?ie=UTF-8&#038;ion=1#hl=en&#038;sclient=psy-ab&#038;q=sql+parameter+null&#038;oq=sql+parameter+null&#038;fp=1">a question for Google</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/procedure-expects-parameter-which-was-not-supplied/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated Version of Random Number Generators</title>
		<link>http://www.csharpcity.com/updated-version-of-random-number-generators/</link>
		<comments>http://www.csharpcity.com/updated-version-of-random-number-generators/#comments</comments>
		<pubDate>Thu, 08 Mar 2012 20:27:04 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[news]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=436</guid>
		<description><![CDATA[After several months, I've finally updated the normally-distributed random number generator to tolerate negative numbers in its range. Thanks to everybody who complained to get this feature done! <a href="http://www.csharpcity.com/updated-version-of-random-number-generators/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After nine months and several requests, many of you will be happy to know that I finally got around to updating the random number generator to allow negative values in ranges when using a normally-distributed random generator.</p>
<p>You can head over to the <a href="/reusable-code/random-number-generators/">Random Number Generators</a> page to download the latest source and binaries. (For those of you who don&#8217;t know, I&#8217;ve published source and binaries for generating random numbers in a normal distribution.)</p>
<p>Thanks to everybody who complained &#8212; if this library was not useful, I would never have gotten around to fixing it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/updated-version-of-random-number-generators/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuring NLog for WCF Services</title>
		<link>http://www.csharpcity.com/configuring-nlog-for-wcf-services/</link>
		<comments>http://www.csharpcity.com/configuring-nlog-for-wcf-services/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 14:38:45 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[NLog]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=430</guid>
		<description><![CDATA[NLog didn't cooperate for my WCF services (server side). I finally did manage to get it working, with a few extra steps; this post outlines how to configure NLog to work with WCF services. <a href="http://www.csharpcity.com/configuring-nlog-for-wcf-services/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>How can you configure WCF services (on the server side) to log to NLog? This is exactly the dillema I found myself in. After scouring the internet for hours, I found little of use; there are apparently many things you need to do properly. So let&#8217;s go ahead and list them out.</p>
<ul>
<li><strong>Install NLog:</strong> Make sure you have NLog installed on the machine which you&#8217;re deploying to. (If you don&#8217;t, you should see your service crash, or errors in your Event Viewer.)</li>
<li><strong>Configure NLog Properly:</strong> Make sure that NLog actually works! You can do this by debugging into the service on your local machine (or via remote debugging). Make sure you have loggers that log both to console and to a log file, as you can verify NLog is working with the former.</li>
<li><strong>Copy NLog.Config to the .svc Directory:</strong> Some people mention that NLog.config should be placed where your .svc file is deployed. In addition to this, I find that <em>you still need a copy in bin</em>. For some reason, having only one log file (either one) didn&#8217;t work, but both together (identical files) worked.</li>
<li><strong>Check Your App Pool:</strong> Another issue I ran into is that IIS had my site configured using the classic pool; I actually had to change it to <em>DefaultAppPool</em>.</li>
<li><strong>Restart IIS:</strong> If you changed anything, restart IIS via the IIS console. It should work.</li>
</ul>
<p>One more thing to mention: <strong>make sure you have some checks in place on the log size.</strong> Depending on your usage, your log files may quickly eat up gigs of space. You can gracefully handle this many ways, the easier being to archive logs every month and simply delete unnecessary ones. I use this configuration for rolling logs:</p>
<p><pre><code>
&lt;targets&gt;
&nbsp;&nbsp;&lt;target name=&quot;logfile&quot; xsi:type=&quot;File&quot; fileName=&quot;${basedir}/MyAwesomeService.log&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;archiveFileName=&quot;${basedir}/archives/log.{#}.txt&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;archiveEvery=&quot;Month&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;archiveNumbering=&quot;Rolling&quot;
&nbsp;&nbsp;&nbsp;&nbsp;maxArchiveFiles=&quot;6&quot; /&gt;
&nbsp;&nbsp;&lt;target name=&quot;console&quot; xsi:type=&quot;Console&quot; /&gt;
&lt;/targets&gt;
</code></pre></p>
<p>This limits my archives to six log files, rotated monthly; on the first of each month, NLog will generate a new file (exactly at midnight!) in /archives, with the filename log.n.txt (for n in {1, 2, &#8230;}).</p>
<p>And it should work! If it doesn&#8217;t, post a comment (especially if you found another piece of configuration or work that needs to be done before NLog cooperates).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/configuring-nlog-for-wcf-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server Indexed Views and View Performance</title>
		<link>http://www.csharpcity.com/sql-server-indexed-views-and-view-performance/</link>
		<comments>http://www.csharpcity.com/sql-server-indexed-views-and-view-performance/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 21:54:30 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=427</guid>
		<description><![CDATA[SQL Server allows you to index views, which caches the results; what's more, indexed views may automatically be included in queries at SQL Server's discretion -- no application changes required. Wow! <a href="http://www.csharpcity.com/sql-server-indexed-views-and-view-performance/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Views are a powerful table-level abstraction. You can combine and transform data from one or more tables (across databases!) into a single, cohesive, pseudo-table. Why &#8220;pseudo-table?&#8221; Views have some caveats, such as being potentially read-only. But that&#8217;s another post for another day.</p>
<p>Anyway, if you use views, you might be wondering how exactly they work, and how they affect performance. Are they cached? Are they more efficient than the equivalent SELECT statements?</p>
<p>As it turns out, the answer is &#8220;it depends.&#8221; SQL Server <strong>allows you to index views</strong> to optimize selection. (Indexing views has some caveats, and it depends on the underlying column types/aggregation.) At any rate, the implementation, according to <a href="http://msdn.microsoft.com/en-us/library/dd171921(v=sql.100).aspx">this MSDN article</a>, is:</p>
<ul>
<li>Indexed views are <strong>cached</strong>, and</li>
<li>Non-indexed views are <strong>expanded as needed</strong> (into their constituent SELECT statement).</li>
</ul>
<p>This means that if you use a view without an index, you can&#8217;t expect any performance gain (or loss) &#8212; it&#8217;s just a logical rearrangement of table data. On the other hand, adding any index will give you the benefit of caching. This means you can <strong>use an indexed view to replace an expensive query</strong>, because SQL Server caches the results. This is very useful if you have huge queries or jumbo, multi-table selects.</p>
<p>What&#8217;s more, the same MSDN page contains a veritable gem of a statement:</p>
<blockquote><p>
In SQL Server Enterprise, the SQL Server query optimizer automatically determines when an indexed view can be used for a given query execution. The view does not need to be referenced directly in the query for the optimizer to use it in the query execution plan. <strong>Therefore, existing applications can take advantage of the indexed views without any changes to the application itself;</strong> only the indexed views have to be created.
</p></blockquote>
<p>That&#8217;s a kicker of a statement. It means you can (secretly) optimize your SQL Server performance on the back-end by <em>creating indexed views, <strong>without changing your application</strong></em>. This makes it easy to create/test/drop/repeat as necessary; no code changes necessary.</p>
<p>Simply amazing. I really suggest you read up on indexed views, and their caveats; they&#8217;re a very useful tool to have in your toolbox if you ever find a performance bottleneck in your database layer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/sql-server-indexed-views-and-view-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio Automatic Version Numbering</title>
		<link>http://www.csharpcity.com/visual-studio-automatic-version-numbering/</link>
		<comments>http://www.csharpcity.com/visual-studio-automatic-version-numbering/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 21:20:37 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[assembly versions]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[visual studio 2010]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=420</guid>
		<description><![CDATA[Visual Studio (2010+) allows you to specify that it should generate (incremental) build versions for your projects. The syntax is quite simple (for AssemblyInfo.cs), but there are a few caveats to know. <a href="http://www.csharpcity.com/visual-studio-automatic-version-numbering/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Visual Studio (2010+) adds a much-requested feature: the ability to automatically increment assembly versions per build. (Prior to this, the only way to update the assembly version was to include a batch file, build script, or some other mechanism tied to the build machine that would update AssemblyInfo.cs.)</p>
<p>As a refresher, the assembly version resides in the file <code>Properties\AssemblyInfo.cs</code>. The file contains assembly-level declarations, which is to say, annotations for various assembly-level meta-data. (If you ever need to add any assembly-level annotations, like configuration for Eazfuscator, this is the place to do it.)</p>
<p>At the end of the file, you will notice a lovely comment block and two attributes:</p>
<p><pre><code>
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the &#039;*&#039; as shown below:
// [assembly: AssemblyVersion(&quot;1.0.*&quot;)]
[assembly: AssemblyVersion(&quot;1.0.0.0&quot;)]
[assembly: AssemblyFileVersion(&quot;1.0.0.0&quot;)]
</code></pre></p>
<p>The comment indicates how you can specify auto-versioning of the assembly version. You might think &#8220;easy, let me update my file like so:&#8221; </p>
<p><pre><code>
[assembly: AssemblyVersion(&quot;1.0.*&quot;)]
[assembly: AssemblyFileVersion(&quot;1.0.0.0&quot;)]
</code></pre></p>
<p>But there&#8217;s a gotcha here: you need to specify <strong>only the AssemblyVersion attribute</strong> for the auto-incrementing to work. With this configuration above, you will still see an assembly version of &#8220;1.0.*&#8221;, strangely enough.</p>
<p>The correct configuration is:</p>
<p><pre><code>
[assembly: AssemblyVersion(&quot;1.0.*&quot;)]
</code></pre></p>
<p>Save, build, and everything will work.</p>
<p>&#8220;Hey, that&#8217;s great,&#8221; you might be thinking. &#8220;Let me just update this through the project properties > Assembly Information button in Visual Studio.&#8221; So you blank out the File Version fields, only to be greeted with this:</p>
<p><img src="http://www.csharpcity.com/wp-content/uploads/2012/01/invalid-file-version.png" alt="" title="Visual Studio doesn&#039;t allow automatic build number syntax." width="452" height="184" class="alignnone size-full wp-image-422" /></p>
<p>That&#8217;s right &#8212; Visual Studio will <em>only let you enter a blank File Version through the AssemblyInfo.cs file,</em> not through the GUI! (Thankfully, if it&#8217;s already blank, and you edit some other properties, Visual Studio won&#8217;t complain.)</p>
<h3 id="toc-the-generated-number">The Generated Number</h3>
<p>You might be curious to know how Visual Studio generates the resulting numbers. In fact, you may wonder why it doesn&#8217;t start at, say, 1.0.1.1 and increment to 1.0.1.2, etc.</p>
<p>The actual details are specified on <a href="http://msdn.microsoft.com/en-us/library/k49w9389(v=vs.110).aspx">this MSDN page</a>. The summary is that:</p>
<ul>
<li>The build number (the third number in the version) is equal to <strong>the number of days since January 1st, 2000.</strong> So if today is January 23rd, 2012, that&#8217;s approximately a value of 4400.</li>
<li>The revision number (the final number in the version) is equal to <strong>the number of seconds since midnight, divided by two.</strong>So a build at midnight will result in 0, while a build at 1am will result in a value of 1800.</li>
</ul>
<p>The end result is that <em>every build results in a different version number</em> (unless you run two builds at the very same second). The other caveat is that, if you have a build machine, you need to <strong>make sure your machine times are synchronized</strong>. Or at least be aware of the fact that a build machine in a different timezone may generate a build that seems newer (or older) than it should be.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/visual-studio-automatic-version-numbering/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding Circular Dependencies in SQL Server</title>
		<link>http://www.csharpcity.com/finding-circular-dependencies-in-sql-server/</link>
		<comments>http://www.csharpcity.com/finding-circular-dependencies-in-sql-server/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 22:10:40 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wndows Forms]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Cascade]]></category>
		<category><![CDATA[Foreign Keys]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=418</guid>
		<description><![CDATA[SQL Server doesn't allow a cycle of foreign keys, nor two or more paths to cascadingly delete rows from a table. Thankfully, there's a script you can use to detect at least table reference cycles. <a href="http://www.csharpcity.com/finding-circular-dependencies-in-sql-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>SQL Server doesn&#8217;t mind circular dependencies in tables. That is, unless you have two tables which refer to each other, and try to add foreign key constraints to both.</p>
<p>Then you&#8217;ll see this (infamous) message:</p>
<p><code>Introducing FOREIGN KEY constraint &#039;FK_Foo&#039; on table &#039;Blah&#039; may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.</code></p>
<p>This message can mean a couple of things; one of them is two ways a deletion can cascade down to the same table (i.e. delete table <code>T</code>, and there are two foreign key cascade deletions to table <code>D</code>). The other is that you&#8217;re trying to add foreign keys in a way that causes a cycle, i.e. it will cascade back to the same table.</p>
<p>Thankfully, <a href="http://blogs.msdn.com/b/sqlazure/archive/2010/07/01/10033575.aspx">Wayne Berry wrote a script to take care of this</a>. It finds and prints out cyclical dependencies, like so:</p>
<p><code>dba.Foo -&gt; dba.Bar -&gt; dba.Foo</code></p>
<p>You can find the full script below.</p>
<p><pre><code>
SET NOCOUNT ON

-- WWB: Create a Temp Table Of All Relationship To Improve Overall Performance
CREATE TABLE #TableRelationships (FK_Schema nvarchar(max), FK_Table nvarchar(max),
&nbsp;&nbsp;&nbsp;&nbsp;PK_Schema nvarchar(max), PK_Table nvarchar(max))

-- WWB: Create a List Of All Tables To Check
CREATE TABLE #TableList ([Schema] nvarchar(max), [Table] nvarchar(max))

-- WWB: Fill the Table List
INSERT INTO #TableList ([Table], [Schema])
SELECT TABLE_NAME, TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES 
WHERE Table_Type = &#039;BASE TABLE&#039;

-- WWB: Fill the RelationShip Temp Table
INSERT INTO #TableRelationships(FK_Schema, FK_Table, PK_Schema, PK_Table)
SELECT
&nbsp;&nbsp;&nbsp;&nbsp;FK.TABLE_SCHEMA,
&nbsp;&nbsp;&nbsp;&nbsp;FK.TABLE_NAME,
&nbsp;&nbsp;&nbsp;&nbsp;PK.TABLE_SCHEMA,
&nbsp;&nbsp;&nbsp;&nbsp;PK.TABLE_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INNER JOIN (
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT i1.TABLE_NAME, i2.COLUMN_NAME
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE i1.CONSTRAINT_TYPE = &#039;PRIMARY KEY&#039;
) PT ON PT.TABLE_NAME = PK.TABLE_NAME

CREATE TABLE #Stack([Schema] nvarchar(max), [Table] nvarchar(max))

GO

-- WWB: Drop SqlAzureRecursiveFind
IF&nbsp;&nbsp;EXISTS (SELECT * FROM sys.objects WHERE object_id = 
&nbsp;&nbsp;&nbsp;&nbsp;OBJECT_ID(N&#039;[dbo].[SqlAzureRecursiveFind]&#039;) AND type in (N&#039;P&#039;, N&#039;PC&#039;))
DROP PROCEDURE [dbo].[SqlAzureRecursiveFind]

GO

-- WWB: Create a Stored Procedure that Recursively Calls Itself
CREATE PROC SqlAzureRecursiveFind
&nbsp;&nbsp;&nbsp;&nbsp;@BaseSchmea nvarchar(max),
&nbsp;&nbsp;&nbsp;&nbsp;@BaseTable nvarchar(max),
&nbsp;&nbsp;&nbsp;&nbsp;@Schmea nvarchar(max),
&nbsp;&nbsp;&nbsp;&nbsp;@Table nvarchar(max),
&nbsp;&nbsp;&nbsp;&nbsp;@Fail nvarchar(max) OUTPUT
AS

&nbsp;&nbsp;&nbsp;&nbsp;SET NOCOUNT ON
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Keep Track Of the Schema and Tables We Have Checked
&nbsp;&nbsp;&nbsp;&nbsp;-- Prevents Looping&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;INSERT INTO #Stack([Schema],[Table]) VALUES (@Schmea, @Table)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;DECLARE @RelatedSchema nvarchar(max)
&nbsp;&nbsp;&nbsp;&nbsp;DECLARE @RelatedTable nvarchar(max)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Select all tables that the input table is dependent on
&nbsp;&nbsp;&nbsp;&nbsp;DECLARE table_cursor CURSOR LOCAL&nbsp;&nbsp;FOR
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT PK_Schema, PK_Table
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM #TableRelationships
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE FK_Schema = @Schmea AND FK_Table = @Table

&nbsp;&nbsp;&nbsp;&nbsp;OPEN table_cursor;

&nbsp;&nbsp;&nbsp;&nbsp;-- Perform the first fetch.
&nbsp;&nbsp;&nbsp;&nbsp;FETCH NEXT FROM table_cursor INTO @RelatedSchema, @RelatedTable;

&nbsp;&nbsp;&nbsp;&nbsp;-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
&nbsp;&nbsp;&nbsp;&nbsp;WHILE @@FETCH_STATUS = 0
&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: If We have Recurred To Where We Start This
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Is a Circular Reference
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Begin failing out of the recursions
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IF (@BaseSchmea = @RelatedSchema AND 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@BaseTable = @RelatedTable)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SET @Fail = @RelatedSchema + &#039;.&#039; + @RelatedTable
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETURN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ELSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DECLARE @Count int
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Check to make sure that the dependencies are not in the stack
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- If they are we don&#039;t need to go down this branch
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT&nbsp;&nbsp;&nbsp;&nbsp;@Count = COUNT(1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;&nbsp;&nbsp;&nbsp;#Stack&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE&nbsp;&nbsp;&nbsp;&nbsp;#Stack.[Schema] = @RelatedSchema AND 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#Stack.[Table] = @RelatedTable
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IF (@Count=0) 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Recurse
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXECUTE SqlAzureRecursiveFind @BaseSchmea, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@BaseTable, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@RelatedSchema, @RelatedTable, @Fail OUTPUT
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IF (LEN(@Fail) &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: If the Call Fails, Build the Output Up
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SET @Fail = @RelatedSchema + &#039;.&#039; + @RelatedTable 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ &#039; -&gt; &#039; + @Fail
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETURN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- This is executed as long as the previous fetch succeeds.
&nbsp;&nbsp;&nbsp;&nbsp;FETCH NEXT FROM table_cursor INTO @RelatedSchema, @RelatedTable;
&nbsp;&nbsp;&nbsp;&nbsp;END

&nbsp;&nbsp;&nbsp;&nbsp;CLOSE table_cursor;
&nbsp;&nbsp;&nbsp;&nbsp;DEALLOCATE table_cursor;&nbsp;&nbsp;&nbsp;&nbsp;

GO&nbsp;&nbsp;&nbsp;&nbsp;

SET NOCOUNT ON

DECLARE @Schema nvarchar(max)
DECLARE @Table nvarchar(max)
DECLARE @Fail nvarchar(max)

-- WWB: Loop Through All the Tables In the Database Checking Each One
DECLARE list_cursor CURSOR FOR
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT [Schema], [Table]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM #TableList

OPEN list_cursor;

-- Perform the first fetch.
FETCH NEXT FROM list_cursor INTO @Schema, @Table;

-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN

&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Clear the Stack (Don&#039;t you love Global Variables)
&nbsp;&nbsp;&nbsp;&nbsp;DELETE #Stack
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Initialize the Input
&nbsp;&nbsp;&nbsp;&nbsp;SET @Fail = &#039;&#039;

&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Check the Table
&nbsp;&nbsp;&nbsp;&nbsp;EXECUTE SqlAzureRecursiveFind @Schema, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Table, @Schema,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Table, @Fail OUTPUT
&nbsp;&nbsp;&nbsp;&nbsp;IF (LEN(@Fail) &gt; 0)
&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- WWB: Failed, Output
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SET @Fail = @Schema + &#039;.&#039; + @Table + &#039; -&gt; &#039; + @Fail
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRINT @Fail
&nbsp;&nbsp;&nbsp;&nbsp;END
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp; -- This is executed as long as the previous fetch succeeds.
&nbsp;&nbsp;&nbsp;&nbsp;FETCH NEXT FROM list_cursor INTO @Schema, @Table;
END

-- WWB: Clean Up
CLOSE list_cursor;
DEALLOCATE list_cursor;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
DROP TABLE #TableRelationships
DROP TABLE #Stack
DROP TABLE #TableList
DROP PROC SqlAzureRecursiveFind
</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/finding-circular-dependencies-in-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails-Style Test Database Creation in ASP.NET MVC</title>
		<link>http://www.csharpcity.com/rails-style-test-database-creation-in-asp-net-mvc/</link>
		<comments>http://www.csharpcity.com/rails-style-test-database-creation-in-asp-net-mvc/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 16:35:56 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Core .NET]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=410</guid>
		<description><![CDATA[How can you get ASP.NET MVC to create your database on the fly for tests? Well, you can, if you use migrations for your application to build the tables, drop and recreate all the tables prior to running any tests. <a href="http://www.csharpcity.com/rails-style-test-database-creation-in-asp-net-mvc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the great things about Ruby on Rails is that it uses three databases: development (for dev), test (for unit and integration tests), and production. The test database is actually <em>created prior to running any of the tests</em>; it uses migrations to build the schema, and plain-text (YAML) files to populate test data as you specified.</p>
<p>Pretty cool.</p>
<p>This is actually possible in ASP.NET MVC (as of MVC3), with a bit of work. You will need:</p>
<ul>
<li>Your ASP.NET MVC application (of course)</li>
<li>MigratorDotNet (or your migrations tool of choice)</li>
<li>Visual Studio Test Framework(or your testing tool of choice)</li>
<li>A bit of practice and ingenuity!</li>
</ul>
<p>Here&#8217;s how it works. Given that you already have your development environment working, along with your set of migrations to create your schema tables (including the core ASP.NET tables if you&#8217;re using the built-in login module), you just need to create a once-per-test-run method that will recreate the database and run the migrations.</p>
<p>Sounds complicated? It&#8217;s not. Here&#8217;s how it would look (with the tool stack listed above):</p>
<p><pre><code>
[AssemblyInitialize] // Run once per test run
public static void RecreateDatabase(TestContext context)
{
&nbsp;&nbsp;DataContext dataContext = new DataContext(connectionString);

&nbsp;&nbsp;// Drop all the foreign keys; they can prevent tables from being dropped
&nbsp;&nbsp;dataContext.ExecuteCommand(@&quot;DECLARE @sqlForeignKeys VARCHAR(MAX)

&nbsp;&nbsp;SELECT @sqlForeignKeys = ISNULL(@sqlForeignKeys,&#039;&#039;) +
&nbsp;&nbsp;&#039;ALTER TABLE dbo.[&#039; + OBJECT_NAME(FK.parent_object_id) + &#039;] DROP CONSTRAINT [&#039; + FK.name + &#039;];&#039; + CHAR(10)
&nbsp;&nbsp;FROM SYS.FOREIGN_KEYS FK

&nbsp;&nbsp;EXEC(@sqlForeignKeys)&quot;);

&nbsp;&nbsp;
&nbsp;&nbsp;// Drop all tables
&nbsp;&nbsp;dataContext.ExecuteCommand(&quot;EXEC sp_MSforeachtable @command1 = \&quot;DROP TABLE ?\&quot;&quot;);

&nbsp;&nbsp;// Run migrations to rebuilt schema
&nbsp;&nbsp;Assembly migrationsAssembly = Assembly.Load(&quot;...&quot;); // main application assembly
&nbsp;&nbsp;Migrator.Migrator m = new Migrator.Migrator(&quot;SqlServer&quot;, connectionString, migrationsAssembly);
&nbsp;&nbsp;m.MigrateToLastVersion();
}
</code></pre></p>
<p>The code is pretty straight forward: we drop all the foreign keys first, then the tables. We use <code>sp_MSforeachtable</code>, which is a stored procedure that iterates over all tables. (We drop foreign keys first, because you can&#8217;t drop a table that has a foreign key pointing to one of its columns.)</p>
<p>Then, we get a hold of our main assembly (the one containing the migrations), and we run those.</p>
<p>And everything just works! The <code>AssemblyInitialize</code> attribute ensures that this code is only run once, when the test assembly is loaded.</p>
<p>And just like that, you have your very own Rails-style database being recreated on-the-fly for running tests. (Depending on your flavour of ORM, you can even add your own seed data here for testing.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/rails-style-test-database-creation-in-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Rendered HTML in ASP.NET MVC3</title>
		<link>http://www.csharpcity.com/testing-rendered-html-in-asp-net-mvc3/</link>
		<comments>http://www.csharpcity.com/testing-rendered-html-in-asp-net-mvc3/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 21:51:12 +0000</pubDate>
		<dc:creator>Ashiq Alibhai, PMP</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[HtmlUnit]]></category>
		<category><![CDATA[IKVM]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.csharpcity.com/?p=407</guid>
		<description><![CDATA[HtmlUnit and IKVM together give you the power to test your ASP.NET MVC3 application. Submit forms, and even verify the resulting HTML! All with a little help from Java, and Steve Anderson. <a href="http://www.csharpcity.com/testing-rendered-html-in-asp-net-mvc3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>ASP.NET applications are still difficult to write automated tests against. Other languages (notably Ruby on Rails) have powerful mechanisms to perform not only unit-level testing, but also integration testing: fetching a set of webpages, performing postbacks, and verifying the HTML from the responses along the way.</p>
<p>MVC3 is partially testable: you can create controllers and request views, even pull items out of the ViewBag. That&#8217;s great, but for many applications, it&#8217;s not enough; you want to be able to actually read the underlying HTML and check for the presence or absense of certain HTML content.</p>
<p>Thankfully, there is an answer. It&#8217;s not simple, but it is relatively straight-forward: deploy your debug directory of your web application onto IIS, and use a .NET conversion of <a href="http://htmlunit.sourceforge.net/">HtmlUnit</a> (a GUI-less browser written in Java) to run on <a href="http://www.ikvm.net/">IKVM</a>, a .NET implementation of the JRE. </p>
<p>Credit for this amazing solution goes to Steve Sanderson, who documented the process (and built the binaries) <a href="http://blog.stevensanderson.com/2010/03/30/using-htmlunit-on-net-for-headless-browser-automation/">on his blog</a>. Essentially, you need to:</p>
<ul>
<li>Deploy your debug environment into IIS (giving you the benefit of seeing real IIS errors that don&#8217;t appear in Casini)
<li>Download the HtmlUnit and IKVM binaries
<li>Add all the appropriate references to your test project
<li>Compile, execute, and rejoice
</ul>
<p>Steve&#8217;s page does a great job of xplaining all the steps; just note that he has a link to the IKVM and HtmlUnit binaries at the end of his post (so you don&#8217;t need to build them yourself).</p>
<p>Once you have your app deployed, testing can be as simple as:</p>
<p><pre><code>
&nbsp;&nbsp;[TestMethod]
&nbsp;&nbsp;public void RequestingSecureUrlRedirectsToLogOn() {
&nbsp;&nbsp;&nbsp;&nbsp;WebClient webClient = new WebClient();
&nbsp;&nbsp;&nbsp;&nbsp;HtmlPage page = (HtmlPage)webClient.getPage(&quot;http://localhost/some/secure/action&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;WebResponse response = page.getWebResponse();
&nbsp;&nbsp;&nbsp;&nbsp;Assert.IsTrue(response.getRequestUrl().toString().EndsWith(&quot;/Account/LogOn&quot;));
&nbsp;&nbsp;}
</code></pre> </p>
<p>Run your tests (Visual Studio test framework in my case), and, tada! More complicated tests are possible (filling out forms, clicking buttons, checking response HTML), all though the HtmlPage API. For example, we could have extended that test to include:</p>
<p><pre><code>
((HtmlInput)page.getElementById(&quot;UserName&quot;)).setValueAttribute(&quot;bob&quot;);
((HtmlInput)page.getElementById(&quot;Password&quot;)).setValueAttribute(&quot;invalid&quot;);
HtmlPage resultsPage = (HtmlPage)loginPage.getElementById(&quot;submit&quot;).click();

string content = resultPage.asXml();
Assert.IsTrue(content.Contains(&quot;Login was unsuccessful.&quot;));
</code></pre></p>
<p>In this case, we filled in the <code>UserName</code> and <code>Password</code> fields, clicked Submit, and checked the HTML of the resulting page &#8212; that it contained an error message.</p>
<p>Pretty slick stuff. I highly recommend it if unit testing is something you prioritize. The potential for integration testing is pretty awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csharpcity.com/testing-rendered-html-in-asp-net-mvc3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

