  

<?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>Caffeinated Coder &#187; Persistence</title>
	<atom:link href="http://www.caffeinatedcoder.com/category/persistence/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caffeinatedcoder.com</link>
	<description>A Grande, Triple Shot, Non-Fat Core Dump by Russell Ball</description>
	<lastBuildDate>Tue, 16 Aug 2011 02:08:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>LINQ to NHibernate: A Vast Improvement</title>
		<link>http://www.caffeinatedcoder.com/linq-to-nhibernate/</link>
		<comments>http://www.caffeinatedcoder.com/linq-to-nhibernate/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 12:56:08 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/linq-to-nhibernate/</guid>
		<description><![CDATA[In honor of the (relatively) new 1.0 status of LINQ to NHibernate, I’ve been spending the last few nights LINQifying some old NHibernate queries I’ve written and I must say that I’ve been very pleased. There have traditionally been two ways of specifying NHibernate queries: HQL and the criteria query API. Although I have an [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>In honor of the (relatively) new <a href="http://ayende.com/Blog/archive/2009/07/26/nhibernate-linq-1.0-released.aspx">1.0 status of LINQ to NHibernate</a>, I’ve been spending the last few nights LINQifying some old NHibernate queries I’ve written and I must say that I’ve been very pleased.</p>
<p>There have traditionally been two ways of specifying NHibernate queries: <a href="https://www.hibernate.org/hib_docs/nhibernate/html/queryhql.html">HQL</a> and the <a href="https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/querycriteria.html">criteria query API</a>.</p>
<p>Although I have an easier time deciphering HQL, which is basically a SQL-like string using classes instead of tables, I’ve tended to use the criteria API because it was somewhat strongly typed and thus easier to maintain with the help of refactoring tools like <a href="http://www.jetbrains.com/resharper/">ReSharper</a>.</p>
<p>Thanks to the new NHibernate LINQ provider, I can now work in a mode that is not only more type safe, but also much more readable.</p>
<p>Look at these before and after queries and judge for yourself:</p>
<p>Before (Criterion API)</p>
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; font-size: 8pt; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; height: 240px; background-color: #f4f4f4;">
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> IList&lt;Call&gt; GetCallsByDate(DateTime beginDate, <span style="color: #0000ff">int</span> interpreterId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     ICriteria criteria = Session.CreateCriteria(<span style="color: #0000ff">typeof</span>(Call))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>         .CreateAlias(<span style="color: #006080">"Customer"</span>, <span style="color: #006080">"Customer"</span>)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>         .Add(Restrictions.Gt(<span style="color: #006080">"StartTime"</span>, beginDate))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>         .Add(</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>            Restrictions.Or(</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span>                 Restrictions.Lt(<span style="color: #006080">"EndTime"</span>, DateTime.Now), Restrictions.IsNull(<span style="color: #006080">"EndTime"</span>)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span>                 )</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>             )</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span>         .Add(Restrictions.Eq(<span style="color: #006080">"Interpreter.Id"</span>, interpreterId))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  12:</span>         .AddOrder(Order.Desc(<span style="color: #006080">"StartTime"</span>))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  13:</span>         .AddOrder(Order.Desc(<span style="color: #006080">"Customer.Name"</span>));</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  14:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  15:</span>     <span style="color: #0000ff">return</span> criteria.List&lt;Call&gt;() <span style="color: #0000ff">as</span> List&lt;Call&gt;;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  16:</span> }</pre>
</div>
</div>
<p>After (LINQ to NHibernate)</p>
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; font-size: 8pt; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">public</span> IList&lt;Call&gt; GetCallsByDateWithLinq(DateTime beginDate, <span style="color: #0000ff">int</span> interpreterId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     var query = from call <span style="color: #0000ff">in</span> Session.Linq&lt;Call&gt;()</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>                     <span style="color: #0000ff">where</span> call.StartTime &gt; beginDate</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>                         &amp;&amp; (call.EndTime == null || call.EndTime &lt; DateTime.Now<span style="color: #0000ff"> </span>)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>                         &amp;&amp; call.Interpreter.Id == interpreterId</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>                     orderby call.StartTime descending, call.Customer.Name</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span>                     select call;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">return</span> query.ToList();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span> }</pre>
</div>
</div>
<p>Apparently the NHibernate guys are still working on a full featured LINQ provider for a future version of NHibernate, but decided that the LINQ provider in the contrib project has been tested enough and used in enough production systems to promote it to RTM status.</p>
<p>The one thing I did notice when peeking at the SQL in Profiler is that the Linq provider produced an extra join that the regular Criteria API figured out wasn’t necessary because I was just referencing the foreign key column in the where clause. I’m guessing that minor differences like this will be addressed in the next version of the provider.</p>
<p>In the meantime, I’m still hooked enough to want to use this approach instead.</p>
<p>If you want to give LINQ to NHibernate a test run, just download and reference the one required dll <a href="https://sourceforge.net/projects/nhibernate/files/NHibernate/2.1.0.GA/NHibernate.Linq-1.0.0.GA-bin.zip/download">here</a> (make sure you’re using the same version of NHibernate).</p>
<p>If you’re still not comfortable with LINQ sytnax, here’s a simple <a href="http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx">example based MSDN tutorial</a> to get you started.</p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=566&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/linq-to-nhibernate/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Does It Make Sense To Use NHibernate in a Sproc-Only Shop?</title>
		<link>http://www.caffeinatedcoder.com/does-it-make-sense-to-use-nhibernate-in-a-sproc-only-shop/</link>
		<comments>http://www.caffeinatedcoder.com/does-it-make-sense-to-use-nhibernate-in-a-sproc-only-shop/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 18:40:37 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>
		<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/?p=539</guid>
		<description><![CDATA[I just got the following email question from a friend: If I&#8217;m stuck in one of those loony shops that mandates that all data access has to be done via stored procedures, will NHibernate buy me much? In other words, if the tool&#8217;s purpose is to eliminate me writing SQL, but I have to write [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I just got the following email question from a friend:</p>
<blockquote><p>If I&#8217;m stuck in one of those loony shops that mandates that all data access has to be done via stored procedures, will NHibernate buy me much? In other words, if the tool&#8217;s purpose is to eliminate me writing SQL, but I have to write SQL anyway, is there a point?</p></blockquote>
<p>I’ve only been using NHibernate for about 6 months and am barely struggling to emerge from the newbie stage, but my gut instinct says that <strong>you would loose about 90% of the benefits if you only ever used sprocs with NHibernate.</strong></p>
<p>However, if I were in my friend’s situation <strong>I would probably still use it</strong>.</p>
<p>Why?</p>
<p>The main reason isn’t because of time or productivity savings, but rather because I would bet on the long-term viability of NHibernate and ORM’s in general.</p>
<p>NHiberate is already pretty mainstream and becoming more popular every day. The fact that Microsoft is now fully invested in the ORM space with the Entity Framework means that it will only be a matter of time before the traditional sproc-only mentality finally disappears from even the most conservative software shops.</p>
<p>In the meantime, I’m guessing that I would be able to speed up that process by introducing NHibernate into my application and my workplace even it would be under less than optimal circumstances and not save me much (if any) time in the short term.</p>
<p><img style="display: inline; margin-left: 0px; margin-right: 0px" src="http://farm3.static.flickr.com/2502/3775828986_f03d8ae9b9.jpg" alt="" align="right" />Based on my experience with human nature, I’m betting that once NHibernate is in the dev and production environments for a while, <strong>the other developers and administrators would get used to it and eventually loosen up enough to let me start mapping directly against tables</strong>. It’s a slight gamble, but one based on pretty predictable human behavioral traits.</p>
<p>If nothing else, it’s much more convincing to show someone a proof of concept based on an existing app in production that you only have to slightly modify rather than on a silly Northwind example.</p>
<p>As far as more technical reasons, I leave this up to the more advanced NHiberate using reader to comment on. My sense is that you could still cut down on some tedious mapping code (right to left assigment stuff), but using Fluent NHibernate’s Auto Mapping feature, but I haven’t tried this out yet on sprocs so that may be (at least for now) a dead end.</p>
<p>Are there any other compelling reasons to use NHibernate if you worked in a shop that mandated using only sprocs for data access?</p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=539&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/does-it-make-sense-to-use-nhibernate-in-a-sproc-only-shop/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Just Say No to Manual CRUD</title>
		<link>http://www.caffeinatedcoder.com/just-say-no-to-manual-crud/</link>
		<comments>http://www.caffeinatedcoder.com/just-say-no-to-manual-crud/#comments</comments>
		<pubDate>Sat, 31 May 2008 18:20:53 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/?p=310</guid>
		<description><![CDATA[I&#8217;ve been working a lot with Castle&#8217;s Active Record and Ruby on Rails in the last month and as a result have written significantly fewer basic CRUD operations and database access code. It&#8217;s been an addictive experience and has caused me to rethink the proper role of hand-written database code (sprocs) within an application. Although [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm4.static.flickr.com/3037/2543149087_00b1262b9f.jpg?v=0" alt="" align="right" /> I&#8217;ve been working a lot with <a href="http://www.castleproject.org/activerecord/index.html">Castle&#8217;s Active Record</a> and <a href="http://www.rubyonrails.org/">Ruby on Rails</a> in the last month and as a result have written significantly fewer basic <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> operations and database access code. It&#8217;s been an addictive experience and has caused me to rethink the proper role of hand-written database code (sprocs) within an application.</p>
<p>Although I feel perfectly comfortable in a set-based world writing SQL, it has traditionally been one of my least favorite areas of coding. Besides being relatively repetitive and tedious, at least when it comes to basic CRUD operations, sprocs are much more difficult to handle when it comes to source control, versioning, debugging, and unit testing.</p>
<p>For example, at my last job we were tasked by auditors to come up with a build and deployment process that included version traceability and rollback capabilities. It was pretty easy to put together an acceptable solution for assemblies, since automatically versioning dll&#8217;s in a trusted way is simple via the AssemblyInfo and rolling them back is trivial since everything is contained in a manageable number of dlls that simply need to be copied from one folder to the next. When it came to sprocs, however, the best we could offer auditors was some hackery around adding comments about the version at the top of each sproc definition file along with a big disclaimer that there was no guarantee that files were not modified by DBA&#8217;s along the way.</p>
<p>At my current job, database code causes us even more trouble because the database is larger and contains more sensitive data (thus making restores more difficult), there is a heavier reliance on shared code, and only the deltas of database code are currently under source control. It feels like I am constantly tracking down some ghost bug that is caused by my local database schema somehow being out of sync with the codebase.</p>
<p>Despite these misgivings, I&#8217;ve dutifully followed the traditional Microsoft recommended best practice of funneling all data access through sprocs up until recently because sprocs were supposedly faster, more secure, and provided a beneficial layer of abstraction.</p>
<p>Although I have heard several arguments against sprocs in the last several years, I recently embarked on a more thorough investigation while trying to convince my team to switch over from using an in-house code generation\sproc-based solution for data access to using NHibernate\ActiveRecord. Here are a few resources I found that present good counter arguments against the conventional sproc wisdom.</p>
<ol>
<li><a href="http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx">Stored procedures are bad, m&#8217;kay?</a>: This classic post that was written by <a href="http://weblogs.asp.net/fbouma">Frans Bouma</a> of <a href="http://www.llblgen.com/defaultgeneric.aspx">LLBLGen</a> fame in 2003 spawned quite the flame war on the topic. Most notably, Frans counters the &#8220;Sprocs are faster because they are compiled&#8221; argument by quoting passages from the SQL Server BOL documentation that clearly suggest otherwise. He also counters security arguments by pointing out that parameterized queries prevent SQL injection just as much as sprocs and that assigning permissions to views and roles provide just as much protection as assigning execute rights on sprocs.</li>
<li><a href="http://www.codinghorror.com/blog/archives/000117.html">Who Needs Stored Procedures, Anyways?</a>: This is also an older post from Jeff Atwood where he nicely summarizes the negative aspects of SQL when compared with a traditional coding languages and came up with the quotable phrase &#8220;Stored Procedures should be considered database assembly language: for use in only the most performance critical situations&#8221;. I definitely think that some developers are reluctant to embrace ORM&#8217;s for the same reasons that many old C++ programmers scoffed at the idea of letting the CLR garbage collector manage memory for them instead of manually doing it themselves with raw pointers.</li>
<li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/05/25/145450.aspx">Why I do not use Stored Procedures</a>: Jeremy Miller dismisses performance arguments by declaring them instances of premature optimization and elaborates on all the problems caused by sprocs when it comes to maintainability, testability, and architecture. He also points out that the touted benefit of allowing DBA&#8217;s to make changes is actually a dangerous practice since it represents a breaking API change from the application&#8217;s point of view and thus should go through thorough regression testing before any DBA should be allowed to make changes.</li>
<li><a href="http://codebetter.com/blogs/karlseguin/archive/2008/01/02/foundations-of-programming-part-6-nhibernate.aspx">Foundations of Programming &#8211; Part 6 &#8211; NHibernate</a>: Besides offering a nice introduction to NHibernate, Karl Sequine provides a nice summary of the historical sproc debate, including a counter point for the increased network traffic argument, which he says is a moot point since most traffic occurs between a app and database servers sitting on the same internal GigE networks where bandwidth is fast, plentiful, and free.</li>
<li><a href="http://www.dotnetrocks.com/default.aspx?showNum=240">DotNetRocks ORM Smackdown</a>: For a more balanced debate, listen to this podcast episode (or download the transcripts) where <a href="http://www.ayende.com/">Oren Eini</a> and <a href="http://blogs.tedneward.com/">Ted Neward</a> face off over the value of ORM&#8217;s in the software industry. Be sure to check out the commentary on the episode in the comment section of this <a href="http://ayende.com/Blog/archive/2007/05/24/The-ORM-Smackdown-at-DotNetRocks.aspx">Ayende post</a> as well as the <a href="http://blogs.tedneward.com/default,month,2007-05.aspx">rebuttal in this post</a> by Ted Neward.</li>
</ol>
<p>In my opinion, one of the strongest denunciations of traditional sproc dogma comes Redmond itself, which seems to be straying from its original sproc recommendations in favor of a more more dynamic SQL generation world-view with its recent release of <a href="http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx">LINQ to SQL</a> and the <a href="http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx">Entity Framework</a>.</p>
<p>If you follow the open source world or program in some language other than .NET, then you&#8217;re bound to feel a little smug right now because ORM&#8217;s have been around for a long time. In fact, I have a vivid memory from 6 years ago of a co-worker who was fresh from the Java world being dumb-founded that Microsoft didn&#8217;t have any ORM solution. He was used to using <a href="http://www.hibernate.org/">HIbernate</a> and the thought of manually mapping database tables to domain objects was hard for him to grasp. Even in the .NET open source world, I&#8217;ve been reading blog posts that sing the praises of <a href="http://www.hibernate.org/343.html">NHibernate</a> and <a href="http://sourceforge.net/projects/ibatisnet/">IBatis.NET</a>, two popular .NET ORM ports, for several years.</p>
<p>On one hand, Microsoft&#8217;s entrance into the fray is good news for ORM enthusiasts since it means that a larger audience of developers will begin to see the technology as legitimate. On the other hand, Microsoft clearly has some catching up to do in this space, so you might want to think twice about starting off with Microsoft&#8217;s offering rather than one of the more proven open source or third party alternatives.</p>
<p>If you are a .NET developer and new to ORM&#8217;s, then I recommend starting out with <a href="http://www.castleproject.org/activerecord/index.html">Castle&#8217;s Active Record</a>, which you can learn in less than an hour by reading this <a href="http://www.castleproject.org/activerecord/gettingstarted/index.html">Getting Started with Active Record</a> tutorial. My co-worker&#8217;s were reluctant to try NHibernate because of the perceived learning curve and the plethora of mapping files required, but they quickly agreed to use Active Record after only a short demo.</p>
<p>If you are a <a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object">POCO</a> purists, which means that you want to keep your domain objects free of any non-business related concerns (such as persistance), then you&#8217;ll want to follow the <a href="http://geekswithblogs.net/johnteague/archive/2008/04/23/using-database-repository-pattern-with-activerecord-with-activerecordmediator.aspx">repository pattern using the ActiveRecordMediator</a> class rather than inheriting from ActiveRecordBase like the tutorial shows. Some of the more experienced ORM users seem to see ActiveRecord as more of a gateway drug to NHibernate and ultimately prefer to forgo the conveniences offered by the ActiveRecord layer in favor of the increased flexibility and loosely coupled design offered by dealing directly with NHibernate instead.</p>
<p>Regardless of the approach taken, I definitely no longer believe that sprocs should play any significant role in any application. The current mandate in the software industry is to strive to lower costs by increasing developer productivity and ORM&#8217;s clearly help to do this by eliminating the need to write and maintain countless simple CRUD sprocs.</p>
<p>It&#8217;s definitely time for all of us .NET developers to abandon our convention sproc wisdom and start playing catch-up with the rest of the industry when it comes to using ORM&#8217;s.</p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=310&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/just-say-no-to-manual-crud/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t Forget to Verigoogle</title>
		<link>http://www.caffeinatedcoder.com/dont-forget-to-verigoogle/</link>
		<comments>http://www.caffeinatedcoder.com/dont-forget-to-verigoogle/#comments</comments>
		<pubDate>Tue, 18 Sep 2007 10:36:20 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/dont-forget-to-verigoogle/</guid>
		<description><![CDATA[I knew that SQL Server 2005 had structured exception handling, but for some reason I assumed that you could only use it within CLR sprocs. Since I still haven&#8217;t actually heard of anyone using CLR sprocs for anything other than demos or sample projects (at least not without being pummeled by hoards of angry DBA&#8217;s), I mostly ignored this new [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: Arial;"><font size="2">I knew that SQL Server 2005 had structured exception handling, but for some reason I assumed that you could only use it within CLR sprocs. Since I still haven&#8217;t actually heard of anyone using CLR sprocs for anything other than demos or sample projects (at least not without being pummeled by hoards of angry DBA&#8217;s), I mostly ignored this new feature until now. </font></span></p>
<p><font size="2"><span style="font-family: Arial;">Today I worked on a sproc that involved over a dozen DML statements (it was a utility sproc to handle security and setup steps for developers as part of our build process, so there is no need to chastise me about it being bad design to have so much logic in the database). The thought of copy-pasting dozens of tedious procedural error handling code snippets was so distasteful to me that I decided to do a quick verigoogle. Verigoogling is my freshly coined word for challenging one of my assumptions through google. </span><span style="font-family: Arial;">I was delighted to discover that this new Try/Catch syntax is available to the masses to be used in plain vanilla sprocs. Instead of </span><span style="font-family: Arial;">checking the @@error variable after each statement, we can now be lazy..er..I mean concise and consolidate all the error handling code into the catch block like we&#8217;re used to doing in good ole&#8217; OOP code. </span></font></p>
<p><font size="2"><span style="font-family: Arial;">For those of you like me who haven&#8217;t been taking advantage of this new feature yet, here is some sample code that demonstrates the how easy it is to use. As for the rest of you, please restrain yourself for making fun of me and go verigoogle one of your own assumptions.</span></font></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><font size="2"><span style="font-size: 8pt; color: blue; font-family: 'Arial','sans-serif';">BEGIN</span><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"> <span style="color: blue;">TRY<o:p></o:p></span></span></font></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><span>      </span><span style="color: blue;">BEGIN</span> <span style="color: blue;">TRANSACTION</span> <o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><o:p>         </o:p><span> </span><span style="color: blue;">DELETE</span> <span style="color: blue;">FROM</span> table1<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><span>   </span><o:p></o:p><span>       </span><span style="color: blue;">DELETE</span> <span style="color: blue;">FROM</span> table2<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><span>   </span><o:p></o:p><span>   </span><span style="color: blue;">COMMIT<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><font size="2"><span style="font-size: 8pt; color: blue; font-family: 'Arial','sans-serif';">END</span><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"> <span style="color: blue;">TRY<o:p></o:p></span></span></font></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><font size="2"><span style="font-size: 8pt; color: blue; font-family: 'Arial','sans-serif';">BEGIN</span><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"> <span style="color: blue;">CATCH<o:p></o:p></span></span></font></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><span>    </span><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: gray;">></span> 0<o:p></o:p><br />
<span>           </span><span><span style="color: blue;">ROLLBACK<o:p></o:p></span></span></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><span style="font-size: 8pt; color: blue; font-family: 'Arial','sans-serif';"><o:p><font size="2"> </font></o:p></span><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><font size="2"><span>    </span><span style="color: blue;">DECLARE</span> @ErrMsg <span style="color: blue;">nvarchar</span><span style="color: gray;">(</span>4000<span style="color: gray;">),</span> @ErrSeverity <span style="color: blue;">int<o:p></o:p></span><br />
<span>     </span><span style="color: blue;">SELECT</span> @ErrMsg <span style="color: gray;">=</span> <span style="color: fuchsia;">ERROR_MESSAGE</span><span style="color: gray;">(),<o:p></o:p></span><br />
<span>     </span>@ErrSeverity <span style="color: gray;">=</span> <span style="color: fuchsia;">ERROR_SEVERITY</span><span style="color: gray;">()<o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal;"><font size="2"><span style="font-size: 8pt; color: gray; font-family: 'Arial','sans-serif';"><o:p> </o:p></span><span style="font-size: 8pt; font-family: 'Arial','sans-serif';"><span>    </span><span style="color: blue;">RAISERROR</span><span style="color: gray;">(</span>@ErrMsg<span style="color: gray;">,</span> @ErrSeverity<span style="color: gray;">,</span> 1<span style="color: gray;">)<o:p></o:p></span></span></font></p>
<p class="MsoNormal"><font size="2"><span style="font-size: 8pt; color: blue; line-height: 115%; font-family: 'Arial','sans-serif';">END</span><span style="font-size: 8pt; line-height: 115%; font-family: 'Arial','sans-serif';"> <span style="color: blue;">CATCH</span></span></font></p>
<p class="MsoNormal"><font size="2"><span style="font-size: 8pt; line-height: 115%; font-family: 'Arial','sans-serif';"><span style="color: blue;"></span></span></font> </p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=177&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/dont-forget-to-verigoogle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First Impressions of the Server Optimistically Named SQL Server 2008</title>
		<link>http://www.caffeinatedcoder.com/first-impressions-of-the-server-optimistically-named-sql-server-2008/</link>
		<comments>http://www.caffeinatedcoder.com/first-impressions-of-the-server-optimistically-named-sql-server-2008/#comments</comments>
		<pubDate>Thu, 28 Jun 2007 23:24:44 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/first-impressions-of-the-server-optimistically-named-sql-server-2008/</guid>
		<description><![CDATA[I have not yet downloaded the new CTP, but the KC User group meeting the other night as well as recent decision that I had to make about whether or not to purchase LiteSpeed has inspired me to do some research into SQL Server 2008. Apparently Microsoft is still a little sensitive from being 2 [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I have not yet downloaded the <a href="https://connect.microsoft.com/SQLServer/content/content.aspx?ContentID=5395">new CTP</a>, but the KC User group meeting the other night as well as recent decision that I had to make about whether or not to purchase LiteSpeed has inspired me to do some research into SQL Server 2008.</p>
<p>Apparently Microsoft is still a little sensitive from being 2 years late on the last version because Dave Campbell spent the first 5 minutes of his <a href="http://download.microsoft.com/download/3/4/7/34708006-E6F6-4A50-A401-1D92225EFC32/DAT201_Campbell.wmv">Tech Ed presentation</a> explaining how they have re-engineered their process to ensure that the next version will be delivered on schedule. For example, they will no longer be checking in features into the CTP codebase unless they are fully completed so early CTP&#8217;s will only include a few fully functional features rather than most of the envisioned features in a half-baked state.</p>
<p>Well, whenever we do get the next version, here are a few features that caught my eye.</p>
<ul>
<li><strong>Merge statements (aka upserts)</strong> &#8211; a nice efficient syntax for loading data into a data warehouse that will allow you to specify either an insert or update based on whether or not a record exists.</li>
</ul>
<blockquote style="margin-right: 0px" dir="ltr">
<blockquote style="margin-right: 0px" dir="ltr">
<p class="MsoNormal" style="margin: 0in 0in 10pt; line-height: normal"><span style="font-family: Arial;"><span style="font-size: 10pt"><em>MERGE INTO FactTable F<br />
USING TransactionTable T ON T.OrderID = F.OrderID<br />
WHEN MATCHED THEN UPDATE<br />
SET F.Quantity = T.Quantity</em></span><span style="font-size: 9pt"></span></span></p>
</blockquote>
</blockquote>
<ul>
<li><strong>Table Valued Parameters</strong> &#8211; allows you to pass in a result-set as a parameter to a sproc of udf.</li>
<li><strong>Resource Governor</strong> &#8211; helps prevent runaway queries that can bring down your server. This is especially helpful if you work someplace that allows ad hoc querying against transactional systems.</li>
<li><strong>Declarative Management Framework</strong> &#8211; the Tech Ed webcast showed a demo where a create table statement was prevented from running in Query Analyzer because it violated a policy that had been set up regarding ownership and schemas. Another demo showed a database in SMS with a warning icon because the shrink DB setting had been enabled that violated a configuration policy.</li>
<li><strong>Dynamic Development</strong> &#8211; a rather vague term, but one example was given that described tagging columns with metadata tags such as &#8216;sensitive&#8217; that would then allow you to do queries to track these categories and also apply policies such as only allowing users to query these columns through a secure connection.</li>
<li><strong>New Data Types</strong> &#8211; The filestream data type allows for a best-of-breed approach to managing blob data that would blend the efficiency of the file system with the manageability of the database (backup, restore, querying). Location and Spatial data types allow for built in support for geo-mapping features.</li>
<li><strong>Change Data Capture</strong> &#8211; a good way to appease the auditors by tracking and exposing changes though a relational interface.</li>
<li><strong>Encryption</strong> &#8211; Also an auditor pleaser. It is supposed to be configurable without any application changes required.</li>
<li><strong>Performance Enhancements and Tracking</strong> &#8211; The biggest gains appear to be in start join optimization and data compression, which takes advantage of the fact that SQL Servers are rarely CPU bound. There are also supposed to be a plethora of performance monitoring tools, which we currently rely on Quest tools to provide us.</li>
</ul>
<p>I&#8217;m looking forward to playing with some of these features. With any luck its name will reflect reality and the upgrade path will be easier than it was with <a href="http://geekswithblogs.net/coredump/archive/2007/06/27/113511.aspx"></a></p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=145&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/first-impressions-of-the-server-optimistically-named-sql-server-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://download.microsoft.com/download/3/4/7/34708006-E6F6-4A50-A401-1D92225EFC32/DAT201_Campbell.wmv" length="141929321" type="video/x-ms-wmv" />
		</item>
		<item>
		<title>I survived a SQL 2005 upgrade and all I got was this lousy blog post&#8230;</title>
		<link>http://www.caffeinatedcoder.com/i-survived-a-sql-2005-upgrade-and-all-i-got-was-this-lousy-blog-post/</link>
		<comments>http://www.caffeinatedcoder.com/i-survived-a-sql-2005-upgrade-and-all-i-got-was-this-lousy-blog-post/#comments</comments>
		<pubDate>Thu, 28 Jun 2007 04:21:45 +0000</pubDate>
		<dc:creator>Russell Ball</dc:creator>
				<category><![CDATA[Persistence]]></category>

		<guid isPermaLink="false">http://www.caffeinatedcoder.com/i-survived-a-sql-2005-upgrade-and-all-i-got-was-this-lousy-blog-post/</guid>
		<description><![CDATA[There was some discussion about SQL Server 2008 at the KC .NET user group meeting last night and I involuntarily winced at the thought of another upgrade because we just finished an intensive migration process a few months ago. In hindsight, the migration went fairly smoothly but it was definitely not a trivial process, nor [...]


No related posts.

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>There was some discussion about SQL Server 2008 at the KC .NET user group meeting last night and I involuntarily winced at the thought of another upgrade because we just finished an intensive migration process a few months ago.</p>
<p>In hindsight, the migration went fairly smoothly but it was definitely not a trivial process, nor was it something that I would want to repeat any time soon. It definitely requires some advanced planning and organized regression testing. I thought I would jot down a few lessons that we learned before I completely block this experience out of my memory.</p>
<p>Here are some quick background stats (mid-sized bank):</p>
<ol>
<li>Apps Tested: 40</li>
<li>Technologies supported: .NET 2.0, 1.1, 1.0, Classic ASP, VB6, PowerBuilder, Access 97</li>
<li>Databases: 25<span></span></li>
<li>Total Tables: 2400</li>
<li>Total DB Objects (sprocs &amp; udf’s): 3500</li>
<li>DTS packages: 100</li>
<li>Server implementation: Clustered Quadzilla running on 32 bit Standard Edition, separate Reporting Server</li>
<li>Total required object changes: 40-50</li>
</ol>
<p>Lessons Learned:<br />
<lessons></lessons></p>
<ol>
<li><strong>The upgrade wizard was helpful but not full-proof.</strong> It caught about 60% of the changes we had to make. If you have separate reports or application logic that runs on specific days (i.e. end of month, start of month, end of quarter, etc), make sure you run profile traces on those days and then use the trace files as input for the upgrade adviser.</li>
<li><strong>Script out all the sprocs and udf’s</strong> and then run the ddl scripts against an upgraded test server. We caught another 20% of the problems through the syntax errors we got when trying to recreate these objects.</li>
<li><strong>Set up an organized regression test of your critical apps</strong>, especially if your business has a low tolerance to risk. The last 20% of our changes were only caught through testing because of dynamically generated SQL or SQL that was embedded within the applications rather than stored as objects within SQL Server.</li>
<li><strong>Carefully review all proposed sproc changes</strong> and when possible compare before and after result sets with a tool like RedGate BeyondCompare. Most of the changes we had were syntax related and easily fixed, however we had to redo a few changed sprocs because of some misunderstandings of how the old *= join syntax worked.</li>
<li><strong>Be on guard for a few hard to spot errors</strong> that might show up later in production. For example, this excerpt from one of our udf’s actually concatenated multiple rows together in SQL 2000, but only returned the first row in 2005. The only way we figured this out was that someone reported that a few of our app generated pdf documents were missing several paragraphs.</li>
<p style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; font-size: 8pt; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4">&nbsp;</p>
<p style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4">&nbsp;</p>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white"><span style="color: #606060">   1:</span> select @para = @para + cast(dgp.Paragraph <span style="color: #0000ff">as</span> varchar(7000)) + '</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4"><span style="color: #606060">   2:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white"><span style="color: #606060">   3:</span>             from DocumentParagraphs dgp</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 74.05%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; height: 20px; background-color: #f4f4f4"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white"><span style="color: #606060">   5:</span>             <span style="color: #0000ff">where</span> dgp.ReportID = @ReportID</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 92.72%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; height: 20px; background-color: #f4f4f4"><span style="color: #606060">   6:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white"><span style="color: #606060">   7:</span>                         and dgp.ActiveFlag = 1</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4"><span style="color: #606060">   8:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white"><span style="color: #606060">   9:</span>             order by dgp.ParagraphOrder</pre>
<li><strong>Do not rely on 8.0 compatibility mode</strong> as a safety net. Dropping back into 8.0 compatibility mode did not make the problems we found magically work.</li>
<li><strong>If you have to move many DTS packages to a new machine, be prepared for some mind-numbing, tedious work.</strong> Each package had to be moved manually with lots of GUI clicks and all inner packages had to be re-selected due to GUID issues. Despite this headache, the DTS process was much smoother than expected and we didn’t have to make any code changes within the packages. We did experience some additional flakiness with SQLMail, but we’re not sure if that is related to SQL 2005 or moving from a single server to a cluster.</li>
<li><strong>Beware Legacy Apps &#8211; </strong>If you have to support an old version of a defunct language like PowerBuilder, make sure that you are nice to the only guy who can support it. It turns out that we really didn’t have one of those guys anymore so a couple of us were forced to stumble around in the IDE for the first time ever in order to search for the offending embedded SQL while under deadline pressure. NOT FUN!</li>
<li><strong>Don’t call undocumented functions!</strong> An old C++ module used by a couple of our legacy apps uses pwdcompare(). We finally got it to work but only by seriously elevating the application’s account permissions.</li>
<li><strong>Access wasn&#8217;t so bad</strong> &#8211; Contrary to all expectations, we really didn’t have any problems with linked tables within our Access databases even though we were stuck on a really old version (Access 97). I expected this to be a nightmare, but it wasn’t.</li>
</ol>
<p>Despite these hassles, the migration was definitely worth the effort for us. We were running up against a memory limit imposed by SQL Server Standard edition with our old server and were starting to experience some painful performance problems. SQL 2005 allowed us to upgrade to a much more powerful machine without having to pay the additional $180,000 in licensing fees that it would have cost us to upgrade all of our servers to the SQL 2000 Enterprise Edition which had support for additional memory.</p>
<img src="http://www.caffeinatedcoder.com/?ak_action=api_record_view&id=144&type=feed" alt="" />

<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.caffeinatedcoder.com/i-survived-a-sql-2005-upgrade-and-all-i-got-was-this-lousy-blog-post/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
