<?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>Brian Sullivan</title>
	<atom:link href="http://www.sullivansoftdev.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sullivansoftdev.com/blog</link>
	<description>From one geek to another</description>
	<lastBuildDate>Thu, 25 Feb 2010 05:13:38 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>I Love Lucy</title>
		<link>http://www.sullivansoftdev.com/blog/2010/02/24/i-love-lucy/</link>
		<comments>http://www.sullivansoftdev.com/blog/2010/02/24/i-love-lucy/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 05:13:38 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=197</guid>
		<description><![CDATA[This past Friday, the Sullivan family got a little bit bigger.
Mom and baby are both doing fine.  I have to say, at least from the daddy perspective, the prior experience definitely helps.  I feel like things are going much easier than they did with our first daughter, Molly.  We&#8217;re still getting quite a bit less [...]]]></description>
			<content:encoded><![CDATA[<p>This past Friday, the Sullivan family got a little bit bigger.</p>
<div id="attachment_198" class="wp-caption alignnone" style="width: 235px"><a href="http://www.sullivansoftdev.com/blog/wp-content/uploads/2010/02/photo-1.jpg"><img class="size-medium wp-image-198" title="Lucy's Eyes" src="http://www.sullivansoftdev.com/blog/wp-content/uploads/2010/02/photo-1-225x300.jpg" alt="" width="225" height="300" /></a><p class="wp-caption-text">Lucy Sullivan</p></div>
<p>Mom and baby are both doing fine.  I have to say, at least from the daddy perspective, the prior experience definitely helps.  I feel like things are going much easier than they did with our first daughter, Molly.  We&#8217;re still getting quite a bit less sleep than normal, but there aren&#8217;t as many unknowns, and we don&#8217;t get stressed out about everything the way we did the first time.</p>
<p>And Lucy herself has been making it pretty easy; she&#8217;s a champion sleeper, just like her daddy!</p>
<p>Needless to say, blogging has taken kind of a back seat, but I hope to start back up again soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2010/02/24/i-love-lucy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Why is the .NET Community Using git?</title>
		<link>http://www.sullivansoftdev.com/blog/2010/02/06/why-is-the-net-community-using-git/</link>
		<comments>http://www.sullivansoftdev.com/blog/2010/02/06/why-is-the-net-community-using-git/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 21:57:02 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=186</guid>
		<description><![CDATA[(Disclaimer: I have minimal experience with DVCSs.  The title of this post is an honest question, and if I&#8217;ve made any incorrect asummptions or gotten something just flat-out wrong, I&#8217;d love to be corrected.  Please let me know in the comments!)
My friend David Mohundro wrote a post the other day with some great tips on [...]]]></description>
			<content:encoded><![CDATA[<p>(Disclaimer: I have minimal experience with DVCSs.  The title of this post is an honest question, and if I&#8217;ve made any incorrect asummptions or gotten something just flat-out wrong, I&#8217;d love to be corrected.  Please let me know in the comments!)</p>
<p>My friend David Mohundro wrote a <a href="http://www.mohundro.com/blog/2010/02/04/SomeTipsOnUsingGitWithWindows.aspx">post</a> the other day with some great tips on using git on Windows.  That got me thinking about why the .NET open-source community has started to coalesce around git as its source control tool of choice.  I know git is the new hotness, but it&#8217;s not the only distributed version control system (DVCS) out there.  In particular, I wonder why <a href="http://mercurial.selenic.com/">Mercurial</a> hasn&#8217;t caught on.  It&#8217;s a DVCS like git, is more compatible with Windows, and is easier for new users to learn (by virtue of simply having fewer commands and using terminology closer to that of older VCSs).</p>
<p>I know that git can be used on Windows using a project called &#8220;msysgit,&#8221; but the fact that that project exists at all should tell us something about git.  Git was developed by Linus Torvalds to be used when working on the Linux kernel, using a combination of C and Linux shell scripts.  The maintainers have very little motivation to make git cross-platform, since it already solves the problem it was designed to solve.  In addition, the maintainers of the msysgit project have not always been very interested in solving the problems of their users, as evidenced by comments like <a href="http://twitter.com/subdigital/status/6775154920">these</a>.</p>
<p>Mercurial, on the other hand, is designed to be cross-platform in the first place  (from the about page on the Mercurial site:  &#8221;Mercurial was designed with platform independence in mind.&#8221;).  It seems to me that it ought to be a more natural fit for people developing on the Windows platform.  And it&#8217;s not as if it&#8217;s some obscure bit of technology used by only a few people; large organizations (e.g. Mozilla and the Python Software Foundation) as well as smaller ones are using it.  On top of that, Codeplex (Microsoft&#8217;s open-source project hosting site) <a href="http://blogs.msdn.com/codeplex/archive/2010/01/22/codeplex-now-supporting-native-mercurial.aspx">now supports Mercurial</a>, and so does <a href="http://googlecode.blogspot.com/2009/04/mercurial-support-for-project-hosting.html">Google Code</a>.  So why git instead of Mercurial?</p>
<p>I have a couple of theories about why lots of .NET devs have made this choice, but please keep in mind the disclaimer at the top of this post.</p>
<ol>
<li><strong>Features</strong> &#8211; Git does have a few features that Mercurial lacks.  Most notably, it has an index or &#8220;staging area&#8221;, which allows you to have more control of what a commit will look like.  Local branching is also a bit different, since git doesn&#8217;t actually create a copy of all the files in the repository when you create a branch.  It would seem to me, though, that the main feature that attracts OSS devs to git is its distributed nature, which fits very well with the OSS workflow, and which Mercurial shares.</li>
<li><strong>A Superior Project Hosting Site in GitHub</strong> &#8211; Almost immediately after its launch, <a href="http://github.com">GitHub</a> became <em>the</em> place to be for open source projects, and for good reason.  The site offers a great user experience, and lots of tools to make maintaining a project easier, such as the network graph and pull requests.  <a href="http://bitbucket.org">Bitbucket</a> aims to do the same for Mercurial, and has some of the same features, but hasn&#8217;t caught on the way GitHub has. (Circular logic there, maybe? Oh, well.)</li>
<li><strong>Rails Envy</strong></li>
</ol>
<p>I hate to say it, but this last one is the one that I suspect may be closest to the truth.   .NET developers, especially ones heavily involved in open source software, have always had a bit of an inferiority complex.  At first we felt inferior to Java devs, who had a big head start on figuring out the limitations of their platform, which led to development of lots of patterns and a plethora of open source tools at their disposal (their culture was a lot more amenable to open source a lot earlier than the Microsoft culture was).  The similarities between the .NET and Java platforms and languages was to the .NET community&#8217;s advantage; it was straightforward to directly port many of the more useful Java tools, and the patterns translated easily.</p>
<p>A few years ago, a shift in who we compared ourselves to began.  We saw how much less friction there was when using a framework like Rails and a malleable language like Ruby.  So, as we did before, the .NET OSS community began adopting the tools and patterns used by those we <del><span style="color: #000000;">envied</span></del> admired.  Some of these things translated pretty well.  The principle of convention over configuration, for example, has nothing to do with platforms; it&#8217;s just a mind shift that .NET OSS devs were willing and eager to make.  The tools, however, can&#8217;t always make the jump.  Windows has always been a second-class citizen when it comes to Rails development (DHH has made his disdain for the platform <a href="http://www.loudthinking.com/arc/000433.html">quite clear</a>), and that tends to create a self-perpetuating cycle.  The existing Rails devs don&#8217;t put much effort into making things like tools and plugins cross-platform, so the experience sucks for devs on Windows, who finally give up and switch to a Mac (or at least do their Rails development on a Linux VM), so nobody&#8217;s clamoring for the tools to work on Windows.  Regardless, many .NET OSS devs tend to use a lot of the same tools as Rails devs.  Things like rake, Cucumber, and, of course, git.  It sometimes seems like we&#8217;re bending over backwards to make tools that weren&#8217;t designed for our environment work for us anyway (e.g. msysgit).</p>
<p>So are the few extra features in git or the better UX on GitHub really enough to justify the friction of using git on Windows, or is it just a cargo-cult mentality?  As I said, I have very little experience with either git or Mercurial, so I may be missing something big.  I&#8217;d love to hear from someone who has experience with both DVCSs to set me straight.</p>
<p>In any case, I hope that at some point, we as .NET developers can get over our inferiority complex and just feel comfortable in our own skin.  That doesn&#8217;t mean using the Microsoft tool every time, but acknowledging that sometimes, just because a tool is useful in one environment, doesn&#8217;t mean it&#8217;s a better fit (let alone the aesthetically superior choice) for ours.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2010/02/06/why-is-the-net-community-using-git/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Developing Against Large Databases</title>
		<link>http://www.sullivansoftdev.com/blog/2010/01/30/developing-against-large-databases/</link>
		<comments>http://www.sullivansoftdev.com/blog/2010/01/30/developing-against-large-databases/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 03:58:29 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=179</guid>
		<description><![CDATA[The database for the main application that I work on is fairly large, about 50 Gb or so.  Not the largest SQL Server database I&#8217;ve seen, by far, but one that is non-trivial to move across the network.  This has a significant impact on the development process of our team.  The size of the database [...]]]></description>
			<content:encoded><![CDATA[<p>The database for the main application that I work on is fairly large, about 50 Gb or so.  Not the largest SQL Server database I&#8217;ve seen, by far, but one that is non-trivial to move across the network.  This has a significant impact on the development process of our team.  The size of the database combined with the mediocre size of the hard drives on the laptops we use means that keeping a local copy of production data is unfeasible.</p>
<p>Getting a local database&#8217;s schema in sync with that on production would be easy, but in our case, that&#8217;s not enough to create a working system.  Our application has a large amount what I call &#8220;static data&#8221;, such as menu structures or sets of permissions.  So getting a database that&#8217;s &#8220;up to date&#8221; means not only getting the schema in sync with production, but also ensuring this static data is up to date as well.</p>
<p>Using some sort of tool for evolutionary database design like Rails ActiveRecord migrations would alleviate some of these problems, because schema and static data changes would be a part of the source code. Developers could just run the migrations on their local databases after they updated from source control.  However, this still wouldn&#8217;t solve the whole problem.  In order to effectively develop features within the application, our developers need a reasonable set of test data so that the system isn&#8217;t just completely empty.</p>
<p>There are tools out there, such as Red Gate&#8217;s <a href="http://www.red-gate.com/products/SQL_Data_Generator/index.htm">SQL Data Generator</a> or the <a href="http://msdn.microsoft.com/en-us/library/dd193262(VS.100).aspx">data generators in Visual Studio</a>, that will do a pretty good job creating test data by looking at database column and table names, foreign keys, and such.  This might work out even for such a large system as ours, except that a lot of key tables have &#8220;polymorphic&#8221; relationships, meaning that the foreign key that they contain could point to the primary key in a number of different tables, depending on the particular piece of data.</p>
<p>For example, say we have an &#8220;Invoices&#8221; table.  We have a multi-tenant system, and our customers often base their invoicing on different things.  Some might base invoices based on each individual service they performed for their clients, while others might base them on the amount of time logged in the time and expense module for a client.  In each case, the invoice database record needs to point back to a record in the table that&#8217;s most relevant, given the customer&#8217;s business processes.  Another example of this kind of relationship might be audit records, which might point back to just about any other table in the system.</p>
<p>Since these &#8220;polymorphic&#8221; associations are not defined as proper foreign keys in the database, those data generation tools wouldn&#8217;t be able to figure out that the columns were foreign keys at all, and as far as I&#8217;ve been able to figure, it&#8217;s not possible to define foreign key relationships with a number of different tables manually.  And even if it were, I don&#8217;t think I could prevent the tool from associating and invoice from a company that bases it&#8217;s invoices on services performed with a time and expense entry.</p>
<p>There are a couple of ways that our developers cope with this, neither of which are ideal.  The first, which most of our team members use, is to develop against one of several shared database instances on our data tier servers.  The problems associated with using shared databases for development are well established; developers simply can&#8217;t be as productive when stepping all over each other with data and schema changes.</p>
<p>The second, which I use, is to keep an instance of the database on an external hard drive.  This keeps me isolated from the changes made by other developers, and it&#8217;s a significantly better experience than using a shared database, but problems start to crop up when I get latest from source control.  Developers will check in source code changes that require data or schema changes in order to work, and my local database won&#8217;t have those changes.</p>
<p>So, at the end of the day, the only reliable way to get an up-to-date copy of the schema is to restore a database from the last backup of production.  Since the database is so big, that restore takes multiple hours, which can seriously impede the development process.  This actually impacts developers using shared databases even more than me, because when one of those shared databases has to be refreshed, multiple developers are put out of commission.</p>
<p>The only way I&#8217;ve thought of to make this a little better is to manually create a script that will cherry-pick a certain number of rows from what&#8217;s essentially the &#8220;root&#8221; table of our database, and spider out to include all the data related to those cherry-picked rows, while also including all rows from the tables that contain static data.  The end result would be a much smaller test database that contains a meaningful subset of production data that could me moved around and refreshed in minutes or seconds rather than hours.  The problems with this idea are that it would be onerous to create the script in the first place, since our database contains over 500 tables, and keeping the script up to date with any changes to tables or columns.</p>
<p>I wish there was an easier answer to this.  I have a few ideas in the back of my head about writing a tool that might help me create those scripts, but I think it would still end up being a very manual process of defining relationships that only a human being with knowledge of the system would be able to come up with.  If any readers have experience with this kind of thing, I&#8217;d love to hear how you dealt with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2010/01/30/developing-against-large-databases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TFS Installation: No Longer Rocket Science</title>
		<link>http://www.sullivansoftdev.com/blog/2010/01/20/tfs-installation-no-longer-rocket-science/</link>
		<comments>http://www.sullivansoftdev.com/blog/2010/01/20/tfs-installation-no-longer-rocket-science/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 02:35:19 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[TFS]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=177</guid>
		<description><![CDATA[I think one of the best things that I&#8217;ve observed in playing around with TFS 2010 was how easy it was to install.  This was a pretty big hurdle in previous versions, but 2010 has installation pared down to a &#8220;Next, Next, Finish&#8221; level of complexity in some simple scenarios.  In particular, the &#8220;Basic&#8221; installation, [...]]]></description>
			<content:encoded><![CDATA[<p>I think one of the best things that I&#8217;ve observed in playing around with TFS 2010 was how easy it was to install.  This was a pretty big hurdle in previous versions, but 2010 has installation pared down to a &#8220;Next, Next, Finish&#8221; level of complexity in some simple scenarios.  In particular, the &#8220;Basic&#8221; installation, which doesn&#8217;t include the SharePoint or Reporting Services components, is brain-dead simple.</p>
<p>In addition, TFS can now be installed on client OSes (Vista and above), and use the free SQL Server Express.  It will even go so far as to install SQL Express for you if you don&#8217;t already have it installed (you probably already do if you&#8217;ve installed Visual Studio).  You can download Beta 2 of TFS 2010 from <a href="http://www.microsoft.com/downloads/details.aspx?familyid=6C70FD8F-615E-4203-A028-ACB2C2B8B88F&amp;displaylang=en">here</a>.</p>
<p>However, if you don&#8217;t want to sully your pristine machine with Beta products, there&#8217;s a fully configured Virtual PC image available for download <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=27d91e63-e33b-4cef-a331-f20d343da9de&amp;displaylang=en">here</a>.</p>
<p>In other words, it&#8217;s pretty trivial now to try out TFS yourself if you&#8217;re stuck on SourceSafe and are looking to try out all the other mainstream options, or (like me) if your shop&#8217;s already using TFS and you&#8217;d like to try your hand at some of the administrative features that are behind lock and key.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2010/01/20/tfs-installation-no-longer-rocket-science/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Plan for 2010</title>
		<link>http://www.sullivansoftdev.com/blog/2010/01/07/a-plan-for-2010/</link>
		<comments>http://www.sullivansoftdev.com/blog/2010/01/07/a-plan-for-2010/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 03:33:02 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=175</guid>
		<description><![CDATA[Everyone on my blogroll is taking the opportunity of the new year to take stock of 2009 and make public plans for 2010, so I thought I would join in.
In 2009, I made an effort to start speaking a little bit more.  I spoke at my first code camp, the Northwest Arkansas Code Camp, on the [...]]]></description>
			<content:encoded><![CDATA[<p>Everyone on my blogroll is taking the opportunity of the new year to take stock of 2009 and make public plans for 2010, so I thought I would join in.</p>
<p>In 2009, I made an effort to start speaking a little bit more.  I spoke at my first code camp, the <a href="http://codecamp.nwadnug.org/">Northwest Arkansas Code Camp</a>, on the Harding and LSU campuses for recruiting trips for my employer, as well as the Baton Rouge .NET User Group.  I hope to continue ramping that up in 2010.  I&#8217;m presenting at my home meeting, the Shreveport .NET User Group, later this month, and I have a trip scheduled to the northwest Arkansas area in March.  I&#8217;d like to make it down to southern Louisiana at some point, too; the guys down in Lafayette and New Orleans in particular need some love.</p>
<p>I also need to step up in promoting the SDNUG this year.  I felt like I was able to kind of coast for a lot of 2009 with our current set of attendees, and didn&#8217;t really make as much of an effort as I could have to make more people aware of the group&#8217;s existence.  I&#8217;ve already begun to remedy that this year by seeking out area software companies and making phone calls, which will hopefully yield some more members.  I need to get on top of speaker scheduling, too, both within the group and without.  There are several group members that I think would make great presenters, I just need to convince them that it&#8217;s a good idea!</p>
<p>I want to start blogging more, as well.  One post a month just isn&#8217;t where I want to be.  I think having a regular schedule will help with that, so I&#8217;m pledging right now in public to post something on my blog at least once a week.  That plan may take a hit when my daughter is born in February, but I&#8217;m going to give it my best effort.</p>
<p>I think something else that may help with blogging is having an area of focus.  I&#8217;ve really been interested in application lifecycle management lately, especially after all the stuff I saw at PDC, so at least for now, I think I&#8217;ll focus on Team System and TFS for a little while.  I&#8217;ve been listening to the back catalog of <a href="www.radiotfs.com">Radio TFS</a>, which has been great, and I plan to seek out other additional resources for ideas. I&#8217;ve recently installed TFS on a virtual machine to play around with, so hopefully that will lead to some ideas, as well.</p>
<p>I hope you had a great 2009; here&#8217;s to 2010!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2010/01/07/a-plan-for-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PDC09 Debrief</title>
		<link>http://www.sullivansoftdev.com/blog/2009/11/23/pdc09-debrief/</link>
		<comments>http://www.sullivansoftdev.com/blog/2009/11/23/pdc09-debrief/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 23:50:46 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=168</guid>
		<description><![CDATA[I&#8217;ve just returned from my first major conference, Microsoft&#8217;s Professional Developers&#8217; Conference in Los Angeles, California.  I have to say, things were a bit different than I expected, but in a good way.  More on why later; first, the play-by-play!
Day 0
The air travel wan&#8217;t as bad as I expected it to be.  A quick hop [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just returned from my first major conference, Microsoft&#8217;s Professional Developers&#8217; Conference in Los Angeles, California.  I have to say, things were a bit different than I expected, but in a good way.  More on why later; first, the play-by-play!</p>
<p><strong>Day 0</strong></p>
<p>The air travel wan&#8217;t as bad as I expected it to be.  A quick hop to Houston, and then 3 hours to LAX.  When I finally got to the hotel (the Westin Bonaventure in downtown LA), I met up with <a href="http://geekswithblogs.net/mikehuguet/Default.aspx">Mike Huguet</a>, a fellow user group leader from Baton Rouge.  We ended up down at the Figueroa Hotel with Chris Koenig, a Developer Evangelist from the South Central district, and enjoyed the open bar they had set up for PDC attendees.  I got to meet <a href="http://www.davebost.com/blog/">Dave Bost</a>, the guy behind the <a href="http://thirstydeveloper.com/">Thirsty Developer podcast</a>, and several other Microsoft employees.  We got a little glimpse into Microsoft culture by talking with these guys, and confirmed that the structure of myriad customer liaisons that Microsoft employs is a bit confusing, even to the insiders!  I had planned to go the Party with Palermo, and still rather wished that I had, but we were having such a good time at the Fig, we decided to stay.  We also ended up eating at this great little greasy spoon that only took cash, and has been open continuously, 24 hours a day, since 1924!</p>
<p><strong>Day 1</strong></p>
<p><strong> </strong>The first day at PDC was pretty much all about Azure.  This was a bit disappointing to me, since the current application that I work on couldn&#8217;t really make much use of the cloud.  We have a relatively small user base (a thousand or so users), so scaling out really wouldn&#8217;t buy us much.  I went to the Future of C# and VB session with Luca Bolongese (who has an <em>amazing</em> Italian accent), but wasn&#8217;t really surprised by much there.  After that, I spent waaaay too much time standing in line to do an Azure hands-on lab.  I missed lunch and a session, and didn&#8217;t even get to finish the lab before the expo hall closed at 3:00.  That did, however, secure me a coveted badge stamp that would get me a free Flip video camera the following day (which my wife is loving for taking quick videos of our daughter Molly).  I went to a session on SQL Azure because I figured the database might be one place that we could actually use the scaling, but afterward I concluded that the sharding required to use it for large sets of data would create too large of an impact on our application.  The last session of the day, on PEX and code contracts, was interesting, and perhaps applicable since we&#8217;re looking to start using unit tests soon, but both technologies are still in the research stage, and may never actually make it into the framework proper.  All in all, a bit of a disappointing first day at the conference, but better things were in store for the next day.</p>
<p>That evening, I attended an &#8220;Influencers&#8221; party with Mike and a couple of guys from my old stomping grounds of Northwest Arkansas, <a href="http://tenanji.com/">Jay Smith</a> and Jon Oswald.  I got to catch up with <a href="http://www.colinneller.com/blog/">Colin Neller</a>, a former co-worker at Data-Tronics and fellow Harding alum, as well as meet other community members that I&#8217;d only heard on podcasts before: <a href="http://weblogs.asp.net/jgalloway/">Jon Galloway</a>, <a href="http://cloudsocket.com/graffiti/">Chris &#8220;Woody&#8221; Woodruff</a>, and even <a href="http://www.hanselman.com">Scott Hanselman</a>.  It was cool to be able to put faces with names, and to see that those people are just human beings like you and me.  Jon in particular comes off as just about the friendliest guy in the world, really cheerful and willing to chat with anybody.  Some pretty nice food at that place, too, sushi and shish kabobs. Nom nom!</p>
<p><strong>Day 2</strong></p>
<p>This is when things really started to get interesting.  The Steven Sinofsky did a pretty good job with his part of the keynote, and of course, the announcement that we would all be getting <a href="http://microsoftpdc.com/tablet">free laptops</a> certainly made him some friends. <img src='http://www.sullivansoftdev.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />   The Gu was great, as usual, despite the quadruple iPhone fail.  With the features he described about Silverlight 4, it&#8217;s really starting to look like a compelling platform.  The Silverlight team have really been killing it. They&#8217;re on a lightning-fast release pace, and not just fluff releases either.  They&#8217;re taking customer feedback, even going so far as to add elevation so that applications can do things outside the normal Silverlight sandbox, which at one point they said they&#8217;d never do.</p>
<p>The sessions were great that day, too.  Scott Hanselman&#8217;s MVC talk was great edu-tainment, and it was great to see some of the new templating features he showed off.  I went to an open source panel, and got to meet <a href="http://tirania.org/blog/">Miguel de Icaza</a>, which was pretty cool.  I also had an interesting conversation with some of the people on the Entity Framework team.  We&#8217;re starting to think  about integrating an ORM into our product, and we were leaning toward NHibernate.  I asked the team members point blank why I should use EF instead.  They were pretty frank with me, and basically said &#8220;NHibernate is a mature product, and we&#8217;re still relatively new to the ORM space, but we&#8217;re making a lot of big strides in version 4.&#8221;  Between POCO support, transparent lazy loading, and the code-only (read &#8220;Fluent&#8221;) configuration model, most of the things on my wish list have been met.  It might be worth some further scrutiny at this point.  This is when I realized that all the stuff about getting to interact with the product teams was real, and not just conference marketing.</p>
<p>That evening, rather than going to the big &#8220;Underground @ PDC&#8221; party (for which there was an <em>enormous</em> line), Mike, Chris, Jay, John, and I hung out at the ESPN Zone, kind of a sports bar/restaurant a la Buffalo Wild Wings.  We had some great discussions about managing communities, Microsoft culture, the MVP program, and the role of Developer Evangelists.  I&#8217;m starting to get the feeling that <em>this</em> is the kind of thing one needs to go to conferences for.  Community leaders can talk via Twitter or email all the time, but it&#8217;s only during conference time that we get to take advantage of the high bandwidth of in-person communication.</p>
<p><strong>Day 3</strong></p>
<p>The third day was all about ALM tools for me.  I went to presentations on MSDeploy, the new Test and Lab Manager, Team System process customization, and a kind of roll-up presentation about starting from a project that just compiles to one that&#8217;s under CI with tests (unit and coded UI).  I also spoke with Microsoft employees from several different teams about our particular difficulties with database deployments.  I&#8217;ve got several ideas now, and I&#8217;m looking forward to seeing if we can reduce some of the pain that we&#8217;re experiencing in that area right now.  By this point in the week, I was pretty wiped out, so I headed to the hotel and crashed.</p>
<p><strong>Takeaways</strong></p>
<ol>
<li>Prefer interactions with product team members and community leaders to attending sessions. You can watch the sessions online later if you miss one you really wanted to see.</li>
<li>Leave your laptop in the hotel room (locked up if you feel it&#8217;s necessary).  You really won&#8217;t use it that much, and carrying it around can start to get painful after a couple of days, particularly if you&#8217;re walking to the convention center from your hotel like I was.</li>
<li>Don&#8217;t go out of your way to get swag. You&#8217;ll probably end up with a bunch of it without even trying anyway, and if you put a dollar value on your time, you&#8217;ll quickly realize that the gizmo you&#8217;re in line for.</li>
</ol>
<p>Overall, it was a great experience.  Given how expensive it was, I don&#8217;t think it&#8217;s something I&#8217;m going to do again soon, but hopefully I can attend some smaller conferences next year. Since TechEd is in New Orleans this year, I think the Louisiana community may try to cook something up for just before or after.  Stay tuned for more info!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2009/11/23/pdc09-debrief/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Single-Project Areas in ASP.NET MVC 2</title>
		<link>http://www.sullivansoftdev.com/blog/2009/11/16/single-project-areas-in-asp-net-mvc-2/</link>
		<comments>http://www.sullivansoftdev.com/blog/2009/11/16/single-project-areas-in-asp-net-mvc-2/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 18:15:16 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=143</guid>
		<description><![CDATA[The ASP.NET MVC framework brought a lot of benefits to the Microsoft web developer, such as easier automated testing and better separation of concerns, but it did come with its share of pain points.  One of those pain points was the difficulty of organizing the files in your web project.  By default, all folders that [...]]]></description>
			<content:encoded><![CDATA[<p>The ASP.NET MVC framework brought a lot of benefits to the Microsoft web developer, such as easier automated testing and better separation of concerns, but it did come with its share of pain points.  One of those pain points was the difficulty of organizing the files in your web project.  By default, all folders that contained views, which were named after the controllers in your application, had to be directly under the &#8220;Views&#8221; folder that was provided by the framework.  For large applications, the number of folders underneath &#8220;Views&#8221; could get quite unwieldy.</p>
<p>To help alleviate this, in the first preview of version 2 of the MVC framework, the concept of &#8220;Areas&#8221; was introduced to allow an additional hierarchical level to controller and view organization.  It was implemented in Preview 1 using separate web projects for each area, each with its own &#8220;Controllers&#8221; and &#8220;Views&#8221; folder.</p>
<p>This was a definite improvement, but there was some pretty quick feedback from the community about the implementation.  Having a separate project for each area means that large solutions would end up with quite a few projects, which can dramatically impact compilation time.  I can speak from experience; the main solution I work on had over 80 projects in it when I first joined my current team.  Build time  was usually about 10 minutes, and that was just compilation, no tests or other things going on in the build.  When we reduced it to three projects, build time went down to about 10 seconds.  Needless to say, as our team starts thinking about doing some MVC work, we don&#8217;t want to go back to that place.</p>
<p>Thankfully, in preview 2, the MVC team provided the ability to create all your areas within a single web project.  This provides all the organizational benefits without the impact to compilation time.  To add areas to your MVC web project, follow these steps:</p>
<ol>
<li> Add a folder named &#8220;Areas&#8221; to your web project.</li>
<li>Add a folder underneath the Areas folder with the name of the area you want to create, &#8220;Accounting&#8221; for example.</li>
<li>Add a folder called &#8220;Controllers&#8221; under the Accounting folder.  Now, when you right-click on this folder, you&#8217;ll get the &#8220;Add Controller&#8221; context menu option.</li>
<li>Add a folder called &#8220;Views&#8221; under the Accounting folder.  This will work just like the Views folder that gets created as part of the MVC project template.  You&#8217;ll have one folder inside the Views folder for each controller in your area.</li>
<li>Add a new class  file to the Accounting folder named &#8220;Routes.cs&#8221;.  This class will need to inherit from AreaRegistration and override the AreaName property.  It should end up looking something like this:
<pre name="code" class="c#">using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MyProject.Areas.Accounting
{
    public class Routes : AreaRegistration
    {
        public override string AreaName
        {
            get { return "accounting"; }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "accounting_default",
                "accounting/{controller}/{action}/{id}",
                new { controller = "Invoices", action = "ShowUnpaid", id = "" }
            );
        }
    }
}</pre>
</li>
<li>You&#8217;ll also need to add a line to your Global.asax.cs file.  Simply call &#8220;AreaRegistration.RegisterAllAreas();&#8221; just before the first call to routes.MapRoute().</li>
</ol>
<p>That&#8217;s it!  Well, almost.  Since you can have more than one area with the same controller name, when you create an ActionLink or something similar, you have to specify which area you intend to link to.  For instance, if you wanted to link to the ShowUnpaid action of the Invoices controller in the Accounting area from some other area, you&#8217;d do it like so:</p>
<pre name="code" class="c#">    &lt;%= Html.ActionLink("Unpaid Invoices", "ShowUnpaid", "Invoices", new {area = "accounting"}, null) %&gt;</pre>
<p>Note that if you&#8217;re linking to a controller from a view within the same area, you don&#8217;t have to specify it in the ActionLink call.</p>
<p>I think this is a great feature, and should allow us to maintain the current level of logical partitioning within our application.  Thanks to the MVC team for putting this in!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2009/11/16/single-project-areas-in-asp-net-mvc-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting Around Some Anonymous Type Headaches with Dynamic LINQ</title>
		<link>http://www.sullivansoftdev.com/blog/2009/09/19/getting-around-some-anonymous-type-headaches-with-dynamic-linq/</link>
		<comments>http://www.sullivansoftdev.com/blog/2009/09/19/getting-around-some-anonymous-type-headaches-with-dynamic-linq/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 02:48:09 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=136</guid>
		<description><![CDATA[Here&#8217;s something that totally slipped under my radar when it first came out:  Dynamic LINQ.  This lets you specify LINQ predicates (where clauses, order bys, etc.) using strings instead of strongly typed lambda expressions.  For example, you can rewrite the following LINQ query:
var orders = from o in db.Orders
     where o.OrderDate [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s something that totally slipped under my radar when it first came out:  <a href="http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx">Dynamic LINQ</a>.  This lets you specify LINQ predicates (where clauses, order bys, etc.) using strings instead of strongly typed lambda expressions.  For example, you can rewrite the following LINQ query:</p>
<pre class="c#">var orders = from o in db.Orders
     where o.OrderDate &gt; DateTime.Now.AddDays(-30)
     select o.OrderID, o.OrderDate;</pre>
<p>as something like this:</p>
<pre class="c#">var orders = db.Orders.Where("OrderDate &gt; @0",
     DateTime.Now.AddDays(-30)).Select("new(OrderID, OrderDate)");</pre>
<p>Now, I know what you&#8217;re saying.  &#8221;Why would I want to give up all that strongly-typed goodness?  Isn&#8217;t that what LINQ was all about?&#8221;  Well, at least for me, this came in handy when dealing with anonymous types.  Since the only way you can pass a LINQ to SQL result (which is usually an IQueryable  anonymous type) to a function is as an IQueryable&lt;T&gt;, there&#8217;s no way in that function to specify a strongly typed predicate.  The compiler only knows what properties an anonymously typed object has inside the scope in which the variable is declared.</p>
<p>Since the overload of &#8220;Where()&#8221; provided by the Dynamic LINQ library (DLL, anyone?) will work with any IQueryable&lt;T&gt;, you can specify predicates on LINQ to SQL results passed into functions, as long as you know what properties the object you passed in has.  Using it reminds me of using the HQL syntax in NHibernate.</p>
<p>You can get the library from the LINQ samples provided by Microsoft <a href="http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx">here</a>.  It&#8217;s just a C# or VB file named Dynamic.(cs/vb) in the LinqSamples\DynamicQuery directory. It includes a bunch of extension methods that provide the extra overloads to the LINQ methods.</p>
<p>Not something I envision using often, since it&#8217;s nice to be able to take advantage of the strong typing when you can get it, but nice to know that it&#8217;s there if you need it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2009/09/19/getting-around-some-anonymous-type-headaches-with-dynamic-linq/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Subclass Difficulties Upgrading to Fluent NHibernate RC 1</title>
		<link>http://www.sullivansoftdev.com/blog/2009/08/27/subclass-difficulties-upgrading-to-fluent-nhibernate-rc-1/</link>
		<comments>http://www.sullivansoftdev.com/blog/2009/08/27/subclass-difficulties-upgrading-to-fluent-nhibernate-rc-1/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 12:55:04 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=134</guid>
		<description><![CDATA[I stumbled across Jason Dentler&#8217;s post on the problems he had upgrading his code to the Release Candidate of Fluent NHibernate today, specifically regarding subclasses.   I ran into some difficulties with subclasses when upgrading to the RC myself, but I was using a table-per-class-hierarchy structure rather than table-per-subclass, so I thought I&#8217;d post my problem [...]]]></description>
			<content:encoded><![CDATA[<p>I stumbled across <a href="http://jasondentler.com/blog/2009/08/fluent-nhibernate-upgrade-to-v1-rc-gotchas/">Jason Dentler&#8217;s post</a> on the problems he had upgrading his code to the Release Candidate of Fluent NHibernate today, specifically regarding subclasses.   I ran into some difficulties with subclasses when upgrading to the RC myself, but I was using a table-per-class-hierarchy structure rather than table-per-subclass, so I thought I&#8217;d post my problem and solution as well.</p>
<p>In the RC, rather than defining your class hierarchy entirely in the mapping of the parent class, you create a SubclassMap for each of your subclasses.  The wiki wasn&#8217;t quite clear about what needed to go into my subclass mappings since, like Jason, my subclasses didn&#8217;t have any extra properties, just redefined behavior.  Turns out to be pretty simple, actually, and I think it ends up clearer than the old method.  Using the old way, I had the following in my parent class map:</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 172px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">DiscriminateSubClassesOnColumn&lt;int&gt;(&#8220;intCampaignTypeID&#8221;, -1)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 172px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">.SubClass&lt;InspectionCampaign&gt;(1, x =&gt; {} )</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 172px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">.SubClass&lt;OBPCampaign&gt;(2, x=&gt; { });</div>
<pre>DiscriminateSubClassesOnColumn&lt;int&gt;("intCampaignTypeID", -1)
                .SubClass&lt;InspectionCampaign&gt;(1, x =&gt; {} )
                .SubClass&lt;OBPCampaign&gt;(2, x=&gt; { });</pre>
<p>This is looks okay, but the empty lambdas are a bit confusing.  Using the new SubclassMap way of doing things, in the parent class map, I just call the following method in the constructor:</p>
<pre>DiscriminateSubclassesOnColumn("MyDiscriminatorColumnName");</pre>
<p>And in each subclass map, I call the following method in the constructor:</p>
<pre>DiscriminatorValue("1");</pre>
<p>Much easier to understand!  The signature for this method threw me off a bit, since my discriminator column is actually an integer, but the DiscriminatorValue method only accepts a string.  FNH seems to handle the conversion, though, because it worked just fine.</p>
<p>Hopefully this will be helpful to someone, at least until the wiki gets updated!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2009/08/27/subclass-difficulties-upgrading-to-fluent-nhibernate-rc-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Case for NHibernate</title>
		<link>http://www.sullivansoftdev.com/blog/2009/08/23/the-case-for-nhibernate/</link>
		<comments>http://www.sullivansoftdev.com/blog/2009/08/23/the-case-for-nhibernate/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 02:36:18 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Fluent NHibernate]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[sprocs]]></category>

		<guid isPermaLink="false">http://www.sullivansoftdev.com/blog/?p=124</guid>
		<description><![CDATA[Recently, my employer has instituted a program called &#8220;Innovator of the Quarter&#8221;.  The idea is for employees to submit ideas, such as new product features, process improvements, or tools to increase productivity, to a committee.  The committee will then pick the idea it thinks has the most merit, and the person who submits the winning [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, my employer has instituted a program called &#8220;Innovator of the Quarter&#8221;.  The idea is for employees to submit ideas, such as new product features, process improvements, or tools to increase productivity, to a committee.  The committee will then pick the idea it thinks has the most merit, and the person who submits the winning idea will get $500 and the chance to implement their idea, or at least build a proof-of-concept.</p>
<p>When this program was first announced, several ideas occurred to me, but the one I thought would result in the greatest benefit for the company (and, admittedly, the greatest reduction of development pain for me) was to use NHibernate for our data access instead of the hand-rolled DAL we currently use.  I put together a proof-of-concept project based on one of our smaller systems (which I unfortunately can&#8217;t share since it&#8217;s proprietary), and wrote up a short explanation of the benefits I thought adopting NHibernate would provide.</p>
<p>I wanted to post the contents of that entire document here (slightly sanitized for product and team names) so that readers could point out any glaring mistakes or make suggestions for additions.  So here it is:</p>
<h2 style="text-align: center;">The Case for NHibernate</h2>
<p style="padding-left: 30px;">One of the most fundamental parts of a system is its data-access strategy.  IT organizations building on the .NET platform have a multitude of options for addressing this part of their systems.  Many of these options are provided by Microsoft itself, while others have grown up out of the open-source community.  They range from thin wrappers over the ADO.NET API, such as the Enterprise Library Data Application Block, which provide similar functionality to plain ADO with an easier-to-use programming model, to full-fledged Object-Relational mapping (ORM) tools, such as the Entity Framework or LINQ to SQL.</p>
<p style="padding-left: 30px;">On our team, data access has traditionally been implemented using tools that operate very close to the ADO “metal”, using stored procedures for much of the application logic.  The reasoning for adopting these tools and practices at the time our first system was created included both developer skillsets and performance benefits.  Not long ago, there was a substantial performance benefit to using stored procedures as opposed to “inline” SQL.  However, with the improvements made to SQL Server, these advantages have been eroded to the point that stored procedures no longer carry much performance advantage over parameterized SQL queries.</p>
<p style="padding-left: 30px;">Since the performance differences between the two are now far less significant, other advantages of the various data-access strategies, and specifically those of ORMs, should be examined.  I will outline here the multiple advantages I believe using NHibernate would bring to our projects.  Examples will be taken from the proof-of-concept project stored in source control.</p>
<h2 style="padding-left: 30px;">Development Time</h2>
<h3 style="padding-left: 30px;">CRUD</h3>
<p style="padding-left: 30px;">Chief among the advantages of using any ORM tool is the reduction in development time that is possible if the tool is used appropriately.  In particular, the standard Create, Read, Update, and Delete (CRUD) operations that commonly need to be performed on any business entity are easier to implement using an ORM tool.  Take, for example, the Contact entity from the proof of concept system, which looks something like this:</p>
<p style="padding-left: 30px;"><img class="alignnone size-full wp-image-125" title="class" src="http://www.sullivansoftdev.com/blog/wp-content/uploads/2009/08/class.bmp" alt="class" /></p>
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">In order to implement persistence for an entity like this using stored procedures, we would need a minimum of four procedures, one each for INSERT, UPDATE, SELECT and DELETE.  Also, application code must also be written to put the data into the appropriate properties of a .NET object when retrieved from the database, and from the .NET object properties to stored procedure parameters when saving back to the database.  This sort of “right-hand, left-hand” code is tedious and time-consuming to write, and is really just specifying the same idea four or five times over.  The CRUD procedures for the Contact object in the project the proof-of-concept was based on are about 350 lines of T-SQL put together, and the .NET code to move the properties and parameters back and forth is about 180 lines.</p>
<p style="padding-left: 30px;">On the other hand, using NHibernate mappings, we specify the relationships between our object properties and database table columns in only one place.  Through the use of conventions provided by Fluent NHibernate, these mappings can be specified concisely and clearly.  In the case of the Contact entity, the mapping can be specified in about 30 lines of C# (you can see this in the file ContactMap.cs in the proof of concept project).</p>
<p style="padding-left: 30px;"><script src="http://gist.github.com/174065.js"></script> Once these mappings have been specified, CRUD operations can be executed in the application.  For example, to retrieve a particular Contact from the database, we can simply write:</p>
<pre style="padding-left: 30px;">Contact con = session.Get&lt;Contact&gt;(contactID);</pre>
<p>Where “contactID”  is the primary key value for the contact we want to retrieve.  The “session” object here is a key part of the NHibernate infrastructure; all interactions with the database are executed within a session.  The other 3 CRUD operations are similarly simple.  Examples of each can be seen in the ContactsUC.ascx.cs control in the proof of concept project.</p>
<h4 style="padding-left: 30px;">Delete</h4>
<p><script src="http://gist.github.com/174076.js"></script></p>
<h4 style="padding-left: 30px;">Update</h4>
<p><script src="http://gist.github.com/174092.js"></script></p>
<h4 style="padding-left: 30px;">Create</h4>
<p><script src="http://gist.github.com/174098.js"></script></p>
<h3 style="padding-left: 30px;">Searches</h3>
<p style="padding-left: 30px;">Besides simple retrieval and modification by primary key, the main way that we interact with persistent data is retrieval by a set of more complex criteria.  This is exemplified by the numerous search pages in our systems.  Currently, these searches are accomplished using dynamic SQL generated within a stored procedure.  As anyone who’s ever worked on a search page can attest, these SPs (along with the pages themselves) can get very large very quickly.  This approach necessitates the use of significant conditional logic within the T-SQL code, which can make the procedure quite confusing due to the limited methods of encapsulation provided by the language and environment.</p>
<p style="padding-left: 30px;">There are a couple of options for doing these complex searches using NHibernate:  the Criteria API and the new LINQ provider.  Both of these have their strong points, but it’s what they have in common that’s most important.  They provide a way to execute dynamic queries using only application code without resorting to inline SQL.</p>
<p style="padding-left: 30px;">There are a couple of advantages to using C# to specify searches rather than in T-SQL stored procedures.   The first is in the kinds of tools we have available for achieving logical separation.  Using both native language constructs and refactoring tools, we can break search logic down into much more easily understandable pieces, rather than having to navigate through a sea of IF blocks in T-SQL.  The second advantage is a reduction of duplication.  In our current search implementations, checking search values for nulls, empty strings, etc. occurs in both application and database code.  Using NHibernate, we cut down the number of these checks by half, since we only need to interrogate those values in the application.</p>
<p style="padding-left: 30px;">An example of how a search page might be implemented can be seen in the proof of concept project in Search.aspx.cs.  Note that this page would certainly benefit from additional refactoring, but it should give the reader a general idea of how better separation of concerns and elimination of duplication can be achieved using this method.</p>
<p style="padding-left: 30px;">
<h2 style="padding-left: 30px;">Performance Concerns</h2>
<p style="padding-left: 30px;">As was stated earlier, one of the primary motivations for the data access strategy used by our systems currently was performance, particularly in the area of search.  In order to consider adoption of a new data access strategy, it must be shown that it performs comparably to the current strategy.  Fortunately, SQL Profiler can help us determine the performance impact by showing us the resulting queries produced both by the stored procedures and by NHibernate and the time they take to execute.</p>
<p style="padding-left: 30px;">Though nowhere near exhaustive, the tests I performed showed that the queries produced by NHibernate, when not nearly textually identical to the ones produced by the stored procedures, executed with time differences that were essentially statistically insignificant.  (E.g., 1885 ms vs. 1886 ms)  In fact, in several instances, the NHibernate queries actually performed better than their stored-procedure-produced counterparts.</p>
<p style="padding-left: 30px;">It would be prudent to note, however, that this is only one search page.  Different entity relationships may give rise to situations where SQL hints provided by a developer would have a significant impact on query performance, but this would have to be approached on a case-by-case basis to determine if such optimization is worthwhile.  If such a case does present itself, nothing would prevent us from using a stored procedure to perform that particular operation.  While it is best to be consistent with the data-access methods used in a project, using NHibernate is certainly not an all-or-nothing proposition.</p>
<p style="padding-left: 30px;">When it comes right down to it, NHibernate is an abstraction on top of ADO.NET.  Abstractions are created to increase productivity, not performance.  It may be that in certain cases, the delegation of responsibility to the abstraction layer may result in greater performance due to the elimination of human error or ignorance.  However, a determined developer with intimate knowledge of the underlying technology will often be able to write code that outperforms the abstraction.  In other words, there is no question that an abstraction comes at a price.  The challenge is not to eliminate all abstractions that can be outperformed by hand-tuned code in order to eke out the absolute best performance, but to weigh the benefits and costs of each abstraction to determine if it is, overall, beneficial to the project.</p>
<p style="padding-left: 30px;">The software development industry as a whole is becoming more and more willing to adopt the ORM abstraction.  This can be seen on a number of different platforms, from Ruby on Rails’ ActiveRecord to the Java Hibernate project (upon which NHibernate was originally based).  Microsoft itself has acknowledged the benefits this kind of technology provides, evidenced by their offering of not one, but two ORM solutions:  LINQ to SQL and the Entity Framework.</p>
<h2 style="padding-left: 30px;">Alternatives</h2>
<p style="padding-left: 30px;">NHibernate is hardly the only player in the .NET Object-Relational Mapping space.  Microsoft has two different offerings, LINQ to SQL and the Entity Framework, and there are multiple other commercial and open-source frameworks that offer similar functionality.  So why use NHibernate over these other technologies?</p>
<h3 style="padding-left: 30px;">LINQ to SQL</h3>
<p style="padding-left: 30px;">As Microsoft’s first foray into ORM, LINQ to SQL is a fairly lightweight framework for turning your database tables into entities usable by your application.  For example, if you had a table named “Contact”, you could simply drag that table from the Server Explorer in Visual Studio onto the LINQ to SQL design surface to create a persistent “Contact” class.  This works well for simple scenarios, but LINQ to SQL has several significant limitations.  Among these are only supporting one-to-one mapping between classes and tables, limited support for inherited classes, and a less than stellar workflow for modification of mappings.  In short, LINQ to SQL is likely not a good fit for our existing systems.</p>
<h3 style="padding-left: 30px;">Entity Framework</h3>
<p style="padding-left: 30px;">The ADO.NET Entity Framework is Microsoft’s full-fledged ORM solution.  While it boasts a larger set of features than LINQ to SQL, it also has a number of shortcomings.    Rather than allowing the user to map tables to an existing set of entity classes, EF generates its own new classes that must be used in order to persist data.  Also, lazy-loading of associated entities (e.g. waiting to load a set of Contacts belonging to a Location until and only if they are needed) is poorly supported.  In addition to these and other problems, the XML mapping files themselves are tremendously complex, and consequently are very difficult to modify when needed.  While there is hope that some of the problems with EF may be addressed in the upcoming version, its release is tied to Visual Studio 2010, which it still a while off.</p>
<h3 style="padding-left: 30px;">Other Third-Party ORMs</h3>
<p style="padding-left: 30px;">There are a multitude of ORM options for the .NET platform other than the ones already discussed, including SubSonic, LLBLGen, and Telerik’s OpenAccess among others.  Their feature sets vary widely, and while each has its merits, they all share a disadvantage against NHibernate:  the size of their user-base.  Due to its widespread adoption, there are simply more resources for learning about and troubleshooting NHibernate than any other .NET ORM.  When faced with a technical challenge, the availability of online resources can be the difference between solving the problem in a matter of minutes or a matter of days.</p>
<h2 style="padding-left: 30px;">Conclusion</h2>
<p style="padding-left: 30px;">Bottom line, adding the capabilities of NHibernate to our projects will mean increased productivity.  Less time will be spent on repetitive tasks, leaving more time to focus on the problem domain and the needs of our clients.</p>
<p>Any feedback you&#8217;d like to provide in the comments is welcome!</p>
<p><strong>UPDATE:</strong> <a href="http://chrisbenard.net/">Chris Benard</a> suggested that posting the CRUD operations and the mapping would be helpful to people without access to the codebase, and wouldn&#8217;t expose any IP.  I agree, so now it&#8217;s there, in the form of GitHub gists.  Hopefully that&#8217;s an improvement!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sullivansoftdev.com/blog/2009/08/23/the-case-for-nhibernate/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
