<?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>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Code &#187; SQL</title>
	<atom:link href="http://elegantcode.com/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://elegantcode.com</link>
	<description></description>
	<lastBuildDate>Tue, 15 May 2012 10:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ultram For Sale</title>
		<link>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate</link>
		<comments>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 02:12:26 +0000</pubDate>
		<dc:creator>Jarod Ferguson</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/?p=4786</guid>
		<description><![CDATA[Ultram For Sale, A common complaint of the Entity Framework is slow insert times for larger datasets. Ultram overnight, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this post a while back from Mikael Eliasson [...]]]></description>
			<content:encoded><![CDATA[<p> <p> <b>Ultram For Sale</b>, A common complaint of the Entity Framework is slow insert times for larger datasets.  <b>Ultram overnight</b>, Last night I was trying to insert a catalog of 15k products and it was taking a very long time (I gave up after 5 minutes). I recalled this <a href="http://mikee.se/Archive.aspx/Details/using_the_sqlbulkcopy_to_batch_inserts_20111129">post</a> a while back from Mikael Eliasson demonstrating SqlBulkCopy using .NET, <b>Ultram pharmacy</b>.  <b>Ultram maximum dosage</b>, I had used BCP in SQL server, but not from .NET, <b>Ultram reviews</b>.  <b>Ultram treatment</b>, I took Mikael’s example and roughed out a reusable generic version below, which produced 15k inserts in 2.4s or +- 6200 rows per second, <b>cheap Ultram</b>.  I upped it to 4 catalogs, 224392 rows in 39s, for +- 5750 rps (changing between 4 files), <b>Ultram For Sale</b>.  <b>Buying Ultram online over the counter</b>, These are pretty decent records too, 41 columns and a few of the fields have a meaty char count, <b>Ultram dosage</b>.  <b>Ultram results</b>, Good enough I say.</p>  <p><code>[gist]http://gist.github.com/1681480[/gist]</code></p>  <p><code><span style="font-family: verdana">This works off just a basic list of items which property names match the table column names. Given that most POCO based ORM’s generally match the schema exactly, <b>purchase Ultram for sale</b>, <b>Ultram duration</b>, it works great with EF code first objects.</span></code></p>  <p><code><span style="font-family: verdana">To use I just build up a list of objects, pick the connection string off the DbContext and then call BulkInsert to save to the DB, <b>comprar en línea Ultram, comprar Ultram baratos</b>.  <b>Is Ultram safe</b>, Note that in this case I am just adding items to a List&lt;T&gt;, not the EF DbSet&lt;T&gt;.</span></code></p>  <p><code>[gist]http://gist.github.com/1681888[/gist]</code></p>  <p><code><span style="font-family: verdana"></span></code></p>, <b>Ultram overnight</b>.  Ultram class.  Ultram recreational.  Order Ultram online c.o.d.  Ultram from canadian pharmacy.  Where can i cheapest Ultram online.  Purchase Ultram online.  Order Ultram from mexican pharmacy.  Doses Ultram work.  Is Ultram addictive.  Buy no prescription Ultram online.  Online buy Ultram without a prescription.  My Ultram experience.  Where can i find Ultram online.  Ultram price.  Ultram mg.  Ordering Ultram online.  Ultram images.  Ultram price, coupon.  Fast shipping Ultram.  Real brand Ultram online.  Ultram schedule.  Low dose Ultram.  Buy cheap Ultram no rx.  Purchase Ultram online no prescription.  Ultram pictures.  Discount Ultram.</p>
<p></p>
<p><b>Similar posts:</b> <a href='http://elegantcode.com/?p=4721'>Buy Flonase Without Prescription</a>. <a href='http://elegantcode.com/?p=4234'>Buy Periactin Without Prescription</a>. <a href='http://elegantcode.com/?p=4203'>Buy Armour Without Prescription</a>. <a href='http://elegantcode.com/?p=4899'>Buy Macrobid Without Prescription</a>. <a href='http://elegantcode.com/?p=4534'>Xalatan For Sale</a>. <a href='http://elegantcode.com/?p=4302'>Phenergan wiki</a>. <a href='http://elegantcode.com/?p=4268'>Soma maximum dosage</a>. <a href='http://elegantcode.com/?p=4602'>Zovirax treatment</a>. <a href='http://elegantcode.com/?p=4578'>Cialis price, coupon</a>. <a href='http://elegantcode.com/?p=4189'>Flexeril price</a>.<br />
<b>Trackbacks from:</b> <a href='http://social-blend.com/?p=1007'>Ultram For Sale</a>. <a href='http://www.quarterlives.com/?p=915'>Ultram For Sale</a>. <a href='http://4realz.net/?p=1958'>Ultram For Sale</a>. <a href='http://tayloegray.com/?p=317'>Ultram For Sale</a>. <a href='http://www.macneilbmx.com/blog/?p=5108'>Ultram For Sale</a>. <a href='http://reversemortgagedaily.com/?p=14222'>Fast shipping Ultram</a>. <a href='http://linuxologist.com/?p=976'>Ultram pics</a>. <a href='http://home.officesnapshots.com/?p=138'>Ultram canada, mexico, india</a>. <a href='http://evanrapoport.com/?p=382'>Is Ultram addictive</a>. <a href='http://www.themusclecarplace.com/?p=4011'>Is Ultram addictive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2012/01/26/sqlbulkcopy-for-generic-listt-useful-for-entity-framework-nhibernate/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using TransactionScope with SQLite</title>
		<link>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-transactionscope-with-sqlite</link>
		<comments>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 22:04:37 +0000</pubDate>
		<dc:creator>Jan Van Ryswyck</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/</guid>
		<description><![CDATA[Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet: using(var transaction = new TransactionScope(TransactionScopeOption.Required)) { using(var connection1 = new SQLiteConnection(_connectionString)) { connection1.Open(); ... // Do stuff with the open connection } // Closes the connection (so we think …) using(var connection2 = new SQLiteConnection(_connectionString)) { [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I ran into a little quirk with SQLite. Take a look at the following code snippet:</p>  <pre class="csharpcode"><span class="kwrd">using</span>(var transaction = <span class="kwrd">new</span> TransactionScope(TransactionScopeOption.Required))
{
    <span class="kwrd">using</span>(var connection1 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        connection1.Open();
        
        ... <span class="rem">// Do stuff with the open connection</span>
        
    } <span class="rem">// Closes the connection (so we think …)</span>
    
    <span class="kwrd">using</span>(var connection2 = <span class="kwrd">new</span> SQLiteConnection(_connectionString))
    {
        <span class="rem">// This line of code throws a SQLiteException with an error </span>
        <span class="rem">// code 'Busy' after a certain timeout has been expired</span>
        connection2.Open();          
        
        ... 
    } 
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>

<p>Everything works just fine with the first connection, but the second connection forms a bigger problem. Calling the <em>Open</em> method on the second connection throws a SQLiteException with the message “The database file is locked” and an error code <em>‘Busy’</em> after a particular timeout has been expired. </p>

<p>At first I didn’t have a clue, largely because the <em>TransactionScope</em> was nicely tucked away at a much higher level (NServiceBus deals with transactions for me). But after reading more about the intrinsic behavior of SQLite it all started to make sense. Apparently SQLite supports only one writer at a time. The TransactionScope holds an exclusive writer lock, even when disposing the first connection. Because the first connection cannot fully close itself, opening the second connection results in a lock error.</p>

<p>Hope this helps explain why the obvious isn’t obvious :-).</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/07/02/using-transactionscope-with-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calls to ReportExecutionService.Render() Hang</title>
		<link>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calls-to-reportexecutionservice-render-hang</link>
		<comments>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 23:27:44 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[SQL Server Reporting Services]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/</guid>
		<description><![CDATA[Given: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Given</strong>: One Windows Service, written in C#, using SQL Reporting Services via the SSRS web services.&#160; MyApp.Service waits for work requests to come in, and when it finds them it uses SSRS to generate some PDFs (among a bunch of other stuff).&#160; The Windows Service code is in one project, “myapp.service,” and the code that does all the work is in a shared project, “myapp.core.”.&#160; </p>  <p><strong>Problem:</strong> The raw bytes of the PDF are returned from SSRS by using the class Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService, via the Render() method.&#160; This code works just fine in Dev, Test, and Stage environments – but in Production, without fail, this Render() method hangs and will never return back to the service process.</p>  <p><strong>The Fix:</strong>&#160; This functionality is a small bit in a much larger application, and even the PDF generation is a smallish piece of some larger responsibilities for the service.&#160; So first, I want to isolate the behavior, and then duplicate it.&#160; </p>  <p>I wrote a test windows service consisting of one project, that does one thing: when a timer fires, a hardcoded request to the production Reporting Services is made to get a PDF bytestream.&#160; This service does what is expected in Dev and Stage, but when I tried to install it on Production:</p>  <p><font face="Courier New">An exception occurred while trying to find the installers in the C:\webreader\webreader.svc.exe assembly.      <br />System.Reflection.<strong>ReflectionTypeLoadException</strong>: <strong>Unable to load one or more of the requested types.</strong> Retrieve the LoaderExceptions property for more information.       <br />Aborting installation for C:\webreader\webreader.svc.exe.</font></p>  <p>Can’t load a type?!&#160; So I copy Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll into the program directory, and my test service installs and works perfectly.&#160; Copying the same files into the production service’s directory also fixes the problem.</p>  <p>&#160;</p>  <p>So, if your Reporting Services ASMX calls are hanging, try changing your references over to “Copy Local” and see what happens…</p>  <p>&#160;</p>  <p><strong>Why this is weird:</strong> If those DLLs were missing or corrupt, then why did the original App code load and run (and hang)?&#160; I thought perhaps the wrong version was referenced in the GAC, but no there were NO Microsoft.ReportViewer.*.dll’s registered.&#160; The service installer caught the missing types when the references were all in one assembly, but didn’t have any problems when the references were spread into a 2nd assembly.&#160; </p>  <p>Just when I think “hey, maybe I’m getting a hang of this .NET stuff” a problem like this happens…</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2010/01/25/calls-to-reportexecutionservice-render-hang/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Database Change Management with Tarantino</title>
		<link>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-change-management-with-tarantino</link>
		<comments>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 10:17:12 +0000</pubDate>
		<dc:creator>Ryan Kelley</dc:creator>
				<category><![CDATA[Esoterica]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/</guid>
		<description><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard. Why [...]]]></description>
			<content:encoded><![CDATA[Seeing as how I have not graced these pages with my presence in quite some time. I figured I better get something going. A little while back my team started working with some outside contractors and our make shift way of keeping changes in sync and under control was simply not cutting the mustard.
<h2>Why do we need DB Change management</h2>
Okay then Mr. Developer (or Mrs.), Why do we need source control? We need database change management for the same reason we need source control. To help manage the code and dependencies our applications rely on.
<h4>Recipes for Disaster:</h4>
<blockquote>Team of developers all working/developing off of a central database</blockquote>
<blockquote>Team of developers working/developing off of local database, with no way to keep changes in sync.</blockquote>
So what’s the problem with these recipes? As new features are developed for an application it is very likely that the database will need schema changes to support these features. These could be as simple as new tables or adding a column. If we have schema changes, we have to make sure that the code base for the app is deployed concurrently with the schema changes.

When deploying software to production, code files and libraries can usually be overwritten with a new version. Databases however must be updated intelligently.
<h2>So we’ve got a problem, do we have a solution?</h2>
Enter Tarantino. I was talking with Jarod F. and he said he had heard some stuff about it, but had never used it so I started digging around and found enough pieces to get it working. So first thing I did was head over to the <a href="http://code.google.com/p/tarantino/" target="_blank">Tarantino project</a> site. Starting reading around and then i did a little googling and managed to dig up enough information to really wet my appetite and to get it working. Then Eric Hexter was kind enough to give me some time via IM and cleared up several areas for me.

Before I get into the specifics of how to set all this up, I want to explain how Tarantino finds and keeps changes in sync.
<ol>
	<li>Tarantino is a forward only change management system, you can’t roll back.</li>
	<li>If you use Tarantino, you can’t go make changes by hand manually</li>
	<li>Tarantino uses RedGate SQL Compare if you want, to compare DB Schemas</li>
	<li>Tarantino makes a table in every DB it touches to keep track of what scripts have been executed on that DB</li>
</ol>
The system is based on a set of conventions which allow incremental changes to the database schema. The conventions are to create two subdirectories in your database scripts folder. Create– this is where your inital schema change scripts go. Update – this is where your change scripts should be placed. They should be named with the following convention ####SCRIPTNAME.sql where #### is the script number with leading zeros. This will ensure the first script 0001_first_schema_change.sql would be executed first. There is a third folder, ExistingSchema, that you will need if you are going to start using Tarantino on an app that is already in development or production.

There are two ways to use Tarantino, command line, and as a NAnt task. I will be showing the NAnt task method, as it has the most examples available on the net.
<h4>Project Setup</h4>
So what I have done, is created a very simple project. A class library with a Fluent NHibernate configuration, a test fixture to create the database schema, and two simple entities which I have listed below:
<div class="csharpcode">
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> Order</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> OrderNumber { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> PONumber { get; set; }</pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> IList&lt;OrderItem&gt; OrderItems { get; set;}</pre>
<pre></pre>
<pre class="alt">   <span class="kwrd">public</span> Order()</pre>
<pre>   {</pre>
<pre class="alt">       OrderItems = <span class="kwrd">new</span> List&lt;OrderItem&gt;();</pre>
<pre>   }</pre>
<pre class="alt">}</pre>
<pre></pre>
<pre class="alt"><span class="kwrd">public</span> <span class="kwrd">class</span> OrderItem</pre>
<pre>{</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">int</span> Id { get; set; }</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">string</span> ItemName { get; set; }</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">string</span> Description { get; set; }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

and my NHibernate and Test Fixture setup:
<div class="csharpcode">
<pre class="alt">[TestFixture]</pre>
<pre><span class="kwrd">public</span> <span class="kwrd">class</span> DB_Setup_Fixture</pre>
<pre class="alt">{</pre>
<pre>    <span class="kwrd">private</span> Configuration _configuration;</pre>
<pre class="alt"></pre>
<pre>    [TestFixtureSetUp]</pre>
<pre class="alt">    <span class="kwrd">public</span> <span class="kwrd">void</span> FixtureSetup()</pre>
<pre>    {</pre>
<pre class="alt"></pre>
<pre>        _configuration = Fluently.Configure()</pre>
<pre class="alt">            .Database(MsSqlConfiguration.MsSql2008</pre>
<pre>                          .ConnectionString(c =&gt;</pre>
<pre class="alt">                                            c.FromConnectionStringWithKey(<span class="str">"testData"</span>))</pre>
<pre>                          .UseReflectionOptimizer()</pre>
<pre class="alt">                          .ShowSql())</pre>
<pre>            .Mappings(m =&gt;</pre>
<pre class="alt">                      m.AutoMappings.Add(AutoMap.AssemblyOf&lt;Order&gt;()</pre>
<pre>                                             .Where(x =&gt; x.Namespace.EndsWith(<span class="str">"Domain"</span>))))</pre>
<pre class="alt">            .BuildConfiguration();</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre></pre>
<pre class="alt">    [Test, Explicit, Category(<span class="str">"DBSetup"</span>)]</pre>
<pre>    <span class="kwrd">public</span> <span class="kwrd">void</span> Create_DB_Schema()</pre>
<pre class="alt">    {</pre>
<pre>        var exporter = <span class="kwrd">new</span> SchemaExport(_configuration);</pre>
<pre class="alt">        exporter.Create(<span class="kwrd">true</span>, <span class="kwrd">true</span>);</pre>
<pre></pre>
<pre class="alt">    }</pre>
<pre>}</pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --> <!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<h5>The one thing to make note of here, is that my test is set to explicit, and I gave it a category of “DBSetup”. This will be important once we start configuring NAnt and Tarantino.</h5>
So now we have a very simple application that we can use to play around with Tarantino. To get Tarantino working, I am using the modified NAnt files that CodeCampServer is using. I just copied over their NAnt folder they have checked into source control. There are two NAnt build files that are required to use Tarantino. Disclaimer: I am a total NAnt noob, this is not my usual build utility, but I figured out enough to make it work.
<h4>Common.build</h4>
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database change management --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="rebuildDatabase"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="updateDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Update"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Create"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="dropDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="action"</span> <span class="attr">value</span><span class="kwrd">="Drop"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="manageSqlDatabase"</span> <span class="attr">failonerror</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="manageSqlDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="${action}"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="${database.integrated}"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}"</span></pre>
<pre class="alt">      <span class="attr">username</span><span class="kwrd">="${database.username}"</span></pre>
<pre>      <span class="attr">password</span><span class="kwrd">="${database.password}"</span></pre>
<pre class="alt">        <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${action != 'Drop'}"</span><span class="kwrd">&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Current Database Version: ${usdDatabaseVersion}"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt"></pre>
<pre>  <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">language</span><span class="kwrd">="C#"</span> <span class="attr">prefix</span><span class="kwrd">="migration"</span> <span class="kwrd">&gt;</span></pre>
<pre class="alt">    &lt;references&gt;</pre>
<pre>      &lt;include name=<span class="str">"System.IO.dll"</span> /&gt;</pre>
<pre class="alt">    &lt;/references&gt;</pre>
<pre>    &lt;code&gt;</pre>
<pre class="alt">      &lt;![CDATA[</pre>
<pre>              [Function(<span class="str">"next-migration-number"</span>)]</pre>
<pre class="alt">              <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">string</span> NextMigration(<span class="kwrd">string</span> path  ) {</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre></pre>
<pre class="alt">                  <span class="kwrd">int</span> count=1;</pre>
<pre></pre>
<pre class="alt">                    <span class="kwrd">if</span>(files.Length &gt; 0)</pre>
<pre>                    {</pre>
<pre class="alt">                        <span class="kwrd">string</span> filename = System.IO.Path.GetFileName(files[files.Length-1]);</pre>
<pre></pre>
<pre class="alt">                        <span class="kwrd">try</span></pre>
<pre>                        {</pre>
<pre class="alt">                            count = Convert.ToInt32(filename.Substring(0, 4));</pre>
<pre>                            count++;</pre>
<pre class="alt"></pre>
<pre>                            <span class="kwrd">if</span>(count%2 == 0)</pre>
<pre class="alt">                                count++;</pre>
<pre>                        }</pre>
<pre class="alt">                        <span class="kwrd">catch</span></pre>
<pre>                        {</pre>
<pre class="alt"></pre>
<pre>                        }</pre>
<pre class="alt">                    }</pre>
<pre>                  <span class="kwrd">return</span> <span class="kwrd">string</span>.Format(<span class="str">"{0:0000}"</span>, count);</pre>
<pre class="alt">              }</pre>
<pre>            ]]&gt;</pre>
<pre class="alt">    &lt;/code&gt;</pre>
<pre>  <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

This file sets up most of the plumbing that hooks up the Tarantino NAnt targets for use in the nant.build file
<h4>NAnt.build</h4>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->
<div class="csharpcode">
<pre class="alt"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span>?<span class="kwrd">&gt;</span></pre>
<pre><span class="rem">&lt;!--EXTERNAL_PROPERTIES: usdDatabaseVersion, CCNetLabel--&gt;</span></pre>
<pre class="alt"><span class="kwrd">&lt;</span><span class="html">project</span> <span class="attr">name</span><span class="kwrd">="TarantinoSample"</span> <span class="attr">xmlns</span><span class="kwrd">="http://nant.sf.net/schemas/nant.xsd"</span><span class="kwrd">&gt;</span></pre>
<pre>      <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Initialization --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ************** --&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">buildfile</span><span class="kwrd">="common.build"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">loadtasks</span> <span class="attr">assembly</span><span class="kwrd">="lib\nant\Tarantino.Nant.Tasks.dll"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- Master Properties --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- ***************** --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="company.name"</span> <span class="attr">value</span><span class="kwrd">="Tarantino Test"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="assembly.unittests"</span> <span class="attr">value</span><span class="kwrd">="TarantinoSample.dll"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">    <span class="rem">&lt;!-- Version settings --&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="project.config"</span> <span class="attr">value</span><span class="kwrd">="debug"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Folder references --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.solution"</span> <span class="attr">value</span><span class="kwrd">="src"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="dir.build"</span> <span class="attr">value</span><span class="kwrd">="build"</span> <span class="attr">dynamic</span><span class="kwrd">="true"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Compilation settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="nant.settings.currentframework"</span> <span class="attr">value</span><span class="kwrd">="net-3.5"</span> <span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="file.solution"</span> <span class="attr">value</span><span class="kwrd">="${dir.solution}/${project::get-name()}.sln"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- Database migration settings --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.script.directory"</span> <span class="attr">value</span><span class="kwrd">="dbChangeScripts"</span> <span class="kwrd">/&gt;</span></pre>
<pre>      <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.server"</span> <span class="attr">value</span><span class="kwrd">="localhost"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.name"</span> <span class="attr">value</span><span class="kwrd">="OrderData"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.integrated"</span> <span class="attr">value</span><span class="kwrd">="true"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.username"</span> <span class="attr">value</span><span class="kwrd">="dbuser"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>    <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="database.password"</span> <span class="attr">value</span><span class="kwrd">="P@ssword1"</span> <span class="attr">overwrite</span><span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="rem">&lt;!-- Database Change Management Targets --&gt;</span></pre>
<pre>    <span class="rem">&lt;!-- ********************************** --&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="reset-database"</span> <span class="attr">depends</span><span class="kwrd">="dropDatabase, createDatabase"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">nunit2</span> <span class="attr">failonerror</span><span class="kwrd">="true"</span> <span class="attr">verbose</span><span class="kwrd">="true"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">formatter</span> <span class="attr">type</span><span class="kwrd">="Plain"</span> <span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">test</span> <span class="attr">assemblyname</span><span class="kwrd">="${dir.solution}/bin/${project.config}/${assembly.unittests}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">                <span class="kwrd">&lt;</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre>                    <span class="kwrd">&lt;</span><span class="html">include</span> <span class="attr">name</span><span class="kwrd">="DBSetup"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">                    <span class="kwrd">&lt;</span><span class="html">exclude</span> <span class="attr">name</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre>                <span class="kwrd">&lt;/</span><span class="html">categories</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;/</span><span class="html">test</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">nunit2</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">    <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="db-migration"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">delete</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span>  <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="reset-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">call</span> <span class="attr">target</span><span class="kwrd">="create-versioned-database"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="migrationScriptName"</span> <span class="attr">value</span><span class="kwrd">="${migration::next-migration-number(database.script.directory+'/Update')}_AutoGeneratedMigration.sql"</span><span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files (x86)\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists('c:\program files\red gate\SQL Compare 8\SQLCompare.exe')}"</span> <span class="kwrd">&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">property</span> <span class="attr">name</span><span class="kwrd">="redgate.exe"</span> <span class="attr">value</span><span class="kwrd">="c:\program files\red gate\SQL Compare 8\SQLCompare.exe"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">exec</span></pre>
<pre>              <span class="attr">program</span><span class="kwrd">="${redgate.exe}"</span></pre>
<pre class="alt">              <span class="attr">commandline</span><span class="kwrd">="/f /v /server1:${database.server} /server2:${database.server} /database1:${database.name} /database2:${database.name}Versioned /scriptfile:${database.script.directory}/Update/_New_Script.sql /exclude:Table:usd_AppliedDatabaseScript"</span></pre>
<pre>              <span class="attr">resultproperty</span><span class="kwrd">="execReturnCode"</span></pre>
<pre class="alt">              <span class="attr">failonerror</span> <span class="kwrd">="false"</span><span class="kwrd">/&gt;</span></pre>
<pre>          <span class="kwrd">&lt;</span><span class="html">fail</span> <span class="attr">if</span><span class="kwrd">="${execReturnCode != '0' and execReturnCode != '63'}"</span> <span class="attr">message</span><span class="kwrd">="Redgate Compare Failed!"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql') == false}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">=""</span><span class="kwrd">/&gt;</span></pre>
<pre>              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="---------------------"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">              <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="No Migration Required"</span><span class="kwrd">/&gt;</span></pre>
<pre>        <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">if</span> <span class="attr">test</span><span class="kwrd">="${file::exists(database.script.directory + '/Update/_New_Script.sql')}"</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">            <span class="kwrd">&lt;</span><span class="html">move</span> <span class="attr">file</span><span class="kwrd">="${database.script.directory}/Update/_New_Script.sql"</span> <span class="attr">tofile</span><span class="kwrd">="${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre>            <span class="kwrd">&lt;</span><span class="html">echo</span> <span class="attr">message</span><span class="kwrd">="Created Migration File ${database.script.directory}/Update/${migrationScriptName}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alt">          <span class="kwrd">&lt;/</span><span class="html">if</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre></pre>
<pre class="alt">      <span class="kwrd">&lt;</span><span class="html">target</span> <span class="attr">name</span><span class="kwrd">="create-versioned-database"</span><span class="kwrd">&gt;</span></pre>
<pre>        <span class="kwrd">&lt;</span><span class="html">tstamp</span><span class="kwrd">&gt;&lt;/</span><span class="html">tstamp</span><span class="kwrd">&gt;</span></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">action</span><span class="kwrd">="Drop"</span></pre>
<pre class="alt">            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre>            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre class="alt">            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre>            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre class="alt">            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre></pre>
<pre class="alt">        <span class="kwrd">&lt;</span><span class="html">manageSqlDatabase</span></pre>
<pre>            <span class="attr">scriptDirectory</span><span class="kwrd">="${database.script.directory}"</span></pre>
<pre class="alt">            <span class="attr">action</span><span class="kwrd">="Create"</span></pre>
<pre>            <span class="attr">server</span><span class="kwrd">="${database.server}"</span></pre>
<pre class="alt">            <span class="attr">integratedAuthentication</span><span class="kwrd">="true"</span></pre>
<pre>            <span class="attr">database</span><span class="kwrd">="${database.name}Versioned"</span></pre>
<pre class="alt">            <span class="attr">username</span><span class="kwrd">=""</span></pre>
<pre>            <span class="attr">password</span><span class="kwrd">=""</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alt"></pre>
<pre>      <span class="kwrd">&lt;/</span><span class="html">target</span><span class="kwrd">&gt;</span></pre>
<pre class="alt"></pre>
<pre></pre>
<pre class="alt"><span class="kwrd">&lt;/</span><span class="html">project</span><span class="kwrd">&gt;</span></pre>
</div>
<!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->

Inside this file there are a few pieces that need to be configured for use in your own app, these are all listed under “Master Properties”
<h4>Change script creation</h4>
So without going into too many details, what I have done is created my initial schema using my Unit Test. From here I could script this out to a text file, but what I did was use SQL Compare, comparing my initial schema to an empty database. This gave me my initial SQL script that creates my database.

Just to verify that my initial schema creation script is good, I will have Tarantino create the Versioned database for me using this command:
<blockquote>lib\nant\nant.exe –buildfile:nant.build create-versioned-database</blockquote>
Tarantino then looks in the ExistingSchema folder, runs any scripts found there, then does the same thing for the Updates folder.

In order to test out the change management features, I made a small change to my domain, adding a decimal of cost to the OrderItem class should do the trick. Rebuild my solution, then back to the command line to run my “Create Database Migration Script.bat” file. This file is just running the NAnt task.

What happens then, is NAnt goes out and runs my DBSetup test that is in my project. Which recreates the “OrderData” database. Tarantino then creates the “Versioned” database, then uses SQL Compare to find the changes between the two, and creates a file in the update folder for me named, <strong>0001_AutoGeneratedMigration.sql</strong> <span style="color: #ff0000;">NOTE: It is important to rename this file before it is committed to source control, or before you apply these changes to a database. Tarantino tracks the scripts that have been run by filename.</span>
<h4>Push to Production or Dev</h4>
So I have mentioned two databases so far in this post, OrderData and OrderDataVersioned. These two databases contain no data, that’s not to say that they couldn’t, if you had scripts that put it in. But that is not what they were designed to do. Our app.config is pointing to OrderData, so when we ask NHibernate to build the schema, it drops all the tables and recreates them, losing all data. OrderDataVersioned, is Tarantinos database that is used to keep changes in sync. In our development environment, every dev has a third database, we would call OrderDataProd for instance. This database could have sample data and other information in it. Let’s say, we don’t want to lose our data in this DB so what we do is let Tarantino handle the first two databases, then we deploy our schema changes to our development database. We use this same technique to push changes to production, after backups of course.

We can do this easily with the following command:
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build updateDatabase –D:database.name=OrderDataProd</span></blockquote>
Now when I tried to run this, my database OrderDataProd did not exist, so I went to SQL manager, created it, and then ran the command again, only to be slammed with another error. Since the database existed, Tarantino did not run the create schema script, only the update, which created another error. The next command will create the database I want, by executing the schema creation script, then applying any updates to it.
<blockquote><span style="background-color: #ffffff;">lib\nant\nant.exe –buildfile:nant.build createDatabase –D:database.name=OrderDataProd</span></blockquote>
Bingo! I now have my 3rd database that I can dump data into and start developing on top of. Just to be sure that we can create another change script, and deploy it to this database, I will modify the domain again, by adding a quantity to the OrderItem object. I will leave this step up to you to try out.
<h4>Source Code</h4>
I know the blog formatting sometimes jacks up code samples a lot so I am making all the source for this post available two ways:
<ul>
	<li><a href="http://elegantcode.googlecode.com/files/TarantinoTest.zip" target="_blank">Zip File Download</a></li>
	<li><a href="http://code.google.com/p/elegantcode/source/browse/#svn/trunk/Coders/RyanKelley/TarantinoTest" target="_blank">Elegant Code SVN Repository</a></li>
</ul>
<h3>Information Sources</h3>
<a href="http://www.lostechies.com/blogs/hex/default.aspx" target="_blank">Eric Hexter</a> – Huge Help

<a href="http://code.google.com/p/codecampserver/" target="_blank">CodeCampServer</a>

<a href="http://jeffreypalermo.com/blog/tarantino-project-rsquo-s-database-migrations-screencast/" target="_blank">Palermo and Hexter Screencast on Tarantino</a>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/11/28/database-change-management-with-tarantino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mobile DB Performance Testing: with Hardware</title>
		<link>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mobile-db-performance-testing</link>
		<comments>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 15:58:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[mobile]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Tools and Utilities]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/08/12/mobile-db-performance-testing/</guid>
		<description><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices. 1. Palm Treo 750 (300 Mhz) 2. Palm Treo Pro (600 Mhz) 3. HP iPAQ hw6945 (416 Mhz) – oldest device First change for the previous listings: cpu is not everything.  The iPAQ has a [...]]]></description>
			<content:encoded><![CDATA[NOTE: this is the same post from a week ago, but now I added in performance times from actual devices.

1. <a href="http://www.amazon.com/Palm-Treo-750-Phone-AT/dp/B000KEP1RI">Palm Treo 750</a> (300 Mhz)

2. <a href="http://www.amazon.com/Palm-Unlocked-MicroSD-U-S-Version-Warranty/dp/B001E96PK0">Palm Treo Pro</a> (600 Mhz)

3. <a href="http://www.amazon.com/dp/B000ILDSLO/?tag=googhydr-20&amp;hvadid=3752752799&amp;ref=pd_sl_6y4d63bk3x_b">HP iPAQ hw6945</a> (416 Mhz) – oldest device

First change for the previous listings: cpu is not everything.  The iPAQ has a faster cpu than the  Treo 750, but is slower on most tests (could be memory, or Windows Mobile 5 vs Windows Mobile 6).

A coworker and me were working on some database performance testing for mobile platforms recently.  Our goal was to get some metrics between SQL CE, SQLite, and UltraLite (a Sybase  product).  Actually, that was my goal, my coworker also wanted to test out <a href="http://www.mcobject.com/perst">Perst</a>, which is an OO database – instead of a relational database.

Now a disclaimer: these tests are not authoritative.  This is not a test of everything you could ever want to test on a mobile database.  In fact, the tests are quite simple.  Also, we are not taking money from any group, so the idea is there is not bias either.  But if anyone would like more authoritative tests – send money.

Finally, performance is not the final statistic for any mobile project, so don’t base your decisions strictly on this.  Notably, how to synchronize the database and memory usage are both huge topics.

On running the test: the metrics I’m displaying are from a WinCE 6.0 emulator, running .net cf 3.5.  But not an actual physical device.  Times from a physical device also vary as there are wide differences between device hardware.  On one device I used, the times were 2-3 times faster on the physical device than the emulator.  But the other important info here is .net cf 3.5.  Microsoft reports a 30% performance increase in moving between .net cf 2.0 and .net cf 3.5.

Finally, all times are reported in milliseconds.  So 1000 is 1 second.
<h2>Create Database</h2>
This is the first performance category – and frankly, the one I care the least about.  In the code I write, you create the database once, and work with it from there.  But just in case this does matter to you, here it is.

The tests consists of creating a brand new database, along with a few tables.  Here is the SQL that was executed for SQL CE (and variations on this were used for each of the other databases):
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> T1 (i bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, s nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">UNIQUE</span> <span style="color: #0000ff">INDEX</span> s_idx <span style="color: #0000ff">ON</span> T1 (s)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Product (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> Customer (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, Name nvarchar(50))</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">TABLE</span> ProductOrder (id bigint <span style="color: #0000ff">not</span> <span style="color: #0000ff">null</span> <span style="color: #0000ff">PRIMARY</span> <span style="color: #0000ff">KEY</span>, ProductId bigint, CustomerId bigint, Price <span style="color: #0000ff">decimal</span>, CreatedDate DateTime)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> poc_idx <span style="color: #0000ff">ON</span> ProductOrder (CustomerId)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">INDEX</span> pop_idx <span style="color: #0000ff">ON</span> ProductOrder (ProductId)</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">3500</td>
<td width="42" valign="top">952</td>
<td width="38" valign="top">861</td>
<td width="11" valign="top">925</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3031</td>
<td width="42" valign="top">1530</td>
<td width="38" valign="top">970</td>
<td width="11" valign="top">1730</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">3507</td>
<td width="42" valign="top">2210</td>
<td width="38" valign="top">1964</td>
<td width="11" valign="top">3198</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">4768</td>
<td width="42" valign="top">2428</td>
<td width="39" valign="top">2083</td>
<td width="13" valign="top">4047</td>
</tr>
</tbody></table>
None of them really stand out here.  The difference between 3.5 seconds and 4.7 seconds is negligible to me.
<h2>Insert</h2>
Now this one I care about.  Here we are attempting a bulk insert of 2000 records into the T1 table (see above).  This is a key task if you plan on synchronizing the database with a central server. If you want to see the general code for this, below is the SqlCe code.
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;">
<div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> (DbConnection conn = SqlCeCommon.CreateConnetion())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   3:</span>     conn.<span style="color: #0000ff">Open</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   4:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">using</span> (var txn = conn.BeginTransaction())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   7:</span>         <span style="color: #0000ff">using</span> (DbCommand cmd = conn.CreateCommand())</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   8:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">   9:</span>             cmd.CommandText = "INSERT <span style="color: #0000ff">INTO</span> T1 (i, s) <span style="color: #0000ff">VALUES</span>(@i, @s)";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  10:</span>             var p1 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  11:</span>             var p2 = cmd.CreateParameter();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  12:</span>             p1.ParameterName = "i";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  13:</span>             p2.ParameterName = "s";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  14:</span>             p1.DbType = DbType.Int64;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  15:</span>             p2.DbType = DbType.String;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  16:</span>             p2.<span style="color: #0000ff">Size</span> = 50;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  17:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p1);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  18:</span>             cmd.<span style="color: #0000ff">Parameters</span>.<span style="color: #0000ff">Add</span>(p2);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  19:</span>             cmd.<span style="color: #0000ff">Prepare</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  20:</span>             long <span style="color: #0000ff">key</span> = 1999;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  21:</span>             <span style="color: #0000ff">for</span> (long i = 0; i &lt; nRecords; i++)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  22:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  23:</span>                 <span style="color: #0000ff">key</span> = (3141592621L*<span style="color: #0000ff">key</span> + 2718281829L)%1000000007L;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  24:</span>                 p1.<span style="color: #0000ff">Value</span> = <span style="color: #0000ff">key</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  25:</span>                 p2.<span style="color: #0000ff">Value</span> = System.<span style="color: #0000ff">Convert</span>.ToString(<span style="color: #0000ff">key</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  26:</span>                 cmd.ExecuteNonQuery();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  28:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  29:</span>         txn.<span style="color: #0000ff">Commit</span>();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  30:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"><span style="color: #606060">  31:</span> }</pre>
</div>
</div>
<table border="0" cellspacing="0" cellpadding="2" width="278">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="67" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="68" valign="top">5948</td>
<td width="57" valign="top">3890</td>
<td width="52" valign="top">2877</td>
<td width="34" valign="top">6454</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="68" valign="top">3012</td>
<td width="57" valign="top">2735</td>
<td width="52" valign="top">1845</td>
<td width="34" valign="top">2810</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="68" valign="top">4235</td>
<td width="57" valign="top">3485</td>
<td width="52" valign="top">3157</td>
<td width="34" valign="top">5359</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="68" valign="top">11413</td>
<td width="57" valign="top">9212</td>
<td width="55" valign="top">8586</td>
<td width="42" valign="top">12051</td>
</tr>
</tbody></table>
First off, SQLite wins this one hands down, nudging out UltraLite and handily beating Perst.  As for SQLCE, I don’t know what happened there.
<h2>Update</h2>
This time, take the text column from the T1 table and update it based on the index.  Again, we are executing these updates one at a time (2000 of them), not in bulk.
<table border="0" cellspacing="0" cellpadding="2" width="279">
<tbody>
<tr>
<td width="64" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="54" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="35" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="64" valign="top">Perst</td>
<td width="71" valign="top">1650</td>
<td width="54" valign="top">1386</td>
<td width="53" valign="top">1719</td>
<td width="35" valign="top">1741</td>
</tr>
<tr>
<td width="64" valign="top">SQLite</td>
<td width="71" valign="top">3000</td>
<td width="54" valign="top">2897</td>
<td width="53" valign="top">2696</td>
<td width="35" valign="top">3775</td>
</tr>
<tr>
<td width="64" valign="top">UltraLite</td>
<td width="71" valign="top">9047</td>
<td width="54" valign="top">6309</td>
<td width="53" valign="top">5815</td>
<td width="35" valign="top">6739</td>
</tr>
<tr>
<td width="64" valign="top">SQLCE</td>
<td width="71" valign="top">5851</td>
<td width="54" valign="top">6556</td>
<td width="55" valign="top">6222</td>
<td width="43" valign="top">8215</td>
</tr>
</tbody></table>
Perst blows the competition away in this test, with SQLite not far behind.  But I would say that SQLCE also gave a respectable showing in this test.  Also, and perhaps more interestingly, the performance times between the emulator and the physical devices are not that different – and in the case of SQLCE, the physical device is SLOWER!
<h2>Search Tests</h2>
The next set of test are to perform a search based on Primary Key and by a text column (indexed).  We are searching for all 2000 records that were inserted (from the insert test), but one record at a time.

<strong>Primary Key Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="303">
<tbody>
<tr>
<td width="73" valign="top"></td>
<td width="70" valign="top"><strong>Emulator</strong></td>
<td width="58" valign="top"><strong>Treo 750</strong></td>
<td width="59" valign="top"><strong>Treo Pro</strong></td>
<td width="41" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="73" valign="top">Perst</td>
<td width="70" valign="top">1809</td>
<td width="58" valign="top">1602</td>
<td width="60" valign="top">1507</td>
<td width="40" valign="top">2048</td>
</tr>
<tr>
<td width="72" valign="top">SQLite</td>
<td width="70" valign="top">9868</td>
<td width="58" valign="top">5926</td>
<td width="60" valign="top">5442</td>
<td width="40" valign="top">7980</td>
</tr>
<tr>
<td width="72" valign="top">UltraLite</td>
<td width="70" valign="top">5637</td>
<td width="58" valign="top">4143</td>
<td width="60" valign="top">3829</td>
<td width="40" valign="top">5541</td>
</tr>
<tr>
<td width="72" valign="top">SQLCE</td>
<td width="70" valign="top">17898</td>
<td width="59" valign="top">14330</td>
<td width="62" valign="top">15219</td>
<td width="49" valign="top">15586</td>
</tr>
</tbody></table>
<strong>Indexed Text Column</strong>
<table border="0" cellspacing="0" cellpadding="2" width="308">
<tbody>
<tr>
<td width="83" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="57" valign="top"><strong>Treo 750</strong></td>
<td width="58" valign="top"><strong>Treo Pro</strong></td>
<td width="40" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="82" valign="top">Perst</td>
<td width="69" valign="top">2435</td>
<td width="56" valign="top">2903</td>
<td width="58" valign="top">2243</td>
<td width="40" valign="top">3016</td>
</tr>
<tr>
<td width="82" valign="top">SQLite</td>
<td width="69" valign="top">9838</td>
<td width="56" valign="top">6015</td>
<td width="58" valign="top">5700</td>
<td width="40" valign="top">6470</td>
</tr>
<tr>
<td width="82" valign="top">UltraLite</td>
<td width="69" valign="top">5698</td>
<td width="56" valign="top">4552</td>
<td width="58" valign="top">3904</td>
<td width="40" valign="top">5290</td>
</tr>
<tr>
<td width="82" valign="top">SQLCE</td>
<td width="70" valign="top">16022</td>
<td width="58" valign="top">14435</td>
<td width="61" valign="top">15703</td>
<td width="48" valign="top">15929</td>
</tr>
</tbody></table>
Here you can really see Perst come out into the lead.  But it is the SQLCE times that are rather disheartening.  Problem is they used to be WORSE!  The SQLCE Text is the one test were I did some real performance tuning.  The biggest difference maker was being VERY specific about parameter types and sizes.  (Note: once I did that for SQLCE, I also did the same for the other providers).  Considering where SQLCE came out in this test, I give SQLite and UltraLite a pass – but I was surprised at the (lack of) performance of SQLite in this case.

Also, since both columns were indexed, it is nice to see there was not a noticeable difference between selecting on the primary key verses on an indexed text column.
<h2>Iterate</h2>
This is the most straight forward of the tests.  Make a query that grabs all of the records out of a table, and get the data out of them.  Nice simple loop, no filters.
<table border="0" cellspacing="0" cellpadding="2" width="276">
<tbody>
<tr>
<td width="65" valign="top"></td>
<td width="71" valign="top"><strong>Emulator</strong></td>
<td width="52" valign="top"><strong>Treo 750</strong></td>
<td width="52" valign="top"><strong>Treo Pro</strong></td>
<td width="34" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="65" valign="top">Perst</td>
<td width="71" valign="top">1946</td>
<td width="52" valign="top">1807</td>
<td width="52" valign="top">2225</td>
<td width="34" valign="top">2988</td>
</tr>
<tr>
<td width="65" valign="top">SQLite</td>
<td width="71" valign="top">1081</td>
<td width="52" valign="top">685</td>
<td width="52" valign="top">557</td>
<td width="34" valign="top">880</td>
</tr>
<tr>
<td width="65" valign="top">UltraLite</td>
<td width="71" valign="top">1945</td>
<td width="52" valign="top">1588</td>
<td width="52" valign="top">1146</td>
<td width="34" valign="top">1666</td>
</tr>
<tr>
<td width="65" valign="top">SQLCE</td>
<td width="71" valign="top">1233</td>
<td width="53" valign="top">965</td>
<td width="54" valign="top">688</td>
<td width="40" valign="top">1096</td>
</tr>
</tbody></table>
Here again the differences are negligible between the different databases.  UltaLite and Perst are the slowest, SQLite is the fastest with SQLCE close behind.  But all are between 1 and 2 seconds so who cares.
<h2>Delete</h2>
Again, a simple test.  Delete everything in the table – one record at a time.
<table border="0" cellspacing="0" cellpadding="2" width="293">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="51" valign="top"><strong>Treo 750</strong></td>
<td width="53" valign="top"><strong>Treo Pro</strong></td>
<td width="56" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">6341</td>
<td width="51" valign="top">4905</td>
<td width="53" valign="top">4379</td>
<td width="56" valign="top">7038</td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">2481</td>
<td width="51" valign="top">2137</td>
<td width="53" valign="top">1520</td>
<td width="56" valign="top">2131</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">5488</td>
<td width="51" valign="top">3704</td>
<td width="53" valign="top">3580</td>
<td width="56" valign="top">4089</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">8807</td>
<td width="51" valign="top">8931</td>
<td width="53" valign="top">7816</td>
<td width="56" valign="top">11439</td>
</tr>
</tbody></table>
Some might be surprised by the Perst numbers here.  But after talking it over, this is somewhat expected if you look at the INSERT times.  The INSERT nearly matches the DELETE.  So if it takes a long to to allocate space, it takes a long to remove it as well.  So no supprise that SQLite runs away with this one.
<h2>Join</h2>
OK, this is actually one of the more significant tests.  There is an issue with joins on mobile database – they stink.  And the more you add, the worse they get.  Side issue is you get a VERY limited number of index types (do you want ascending or descending).

Anyway, the test is simple.  If you look at the Create test you will see the tables we are dealing with.  I add  100 rows into the Product table and 50 records into the Customer table, then 5000 records (each customer has order one of each product) into the order table.

Then the test (and what is timed) is to execute the following query and extract the results.
<div id="codeSnippetWrapper" style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;">
<div id="codeSnippet" style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">SELECT</span> c.Name <span style="color: #0000ff">as</span> Customer, p.Name <span style="color: #0000ff">as</span> Product, o.Price</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">FROM</span> ProductOrder o</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum3" style="color: #606060">   3:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Product p <span style="color: #0000ff">on</span> p.ID = o.ProductId</pre>
<!--CRLF-->
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span id="lnum4" style="color: #606060">   4:</span> <span style="color: #0000ff">LEFT</span> <span style="color: #0000ff">OUTER</span> <span style="color: #0000ff">JOIN</span> Customer c <span style="color: #0000ff">on</span> c.ID = o.CustomerID</pre>
<!--CRLF--></div>
</div>
OK, if you are looking at the results, you see a cop-out.  I didn’t get the Perst code written.  Hopefully this will shame my coworker into getting this done.  :) (hi Priyesh).  But you have the other three results.
<table border="0" cellspacing="0" cellpadding="2" width="224">
<tbody>
<tr>
<td width="63" valign="top"></td>
<td width="68" valign="top"><strong>Emulator</strong></td>
<td width="42" valign="top"><strong>Treo 750</strong></td>
<td width="38" valign="top"><strong>Treo Pro</strong></td>
<td width="11" valign="top"><strong>HP iPAQ</strong></td>
</tr>
<tr>
<td width="63" valign="top">Perst</td>
<td width="68" valign="top">--</td>
<td width="42" valign="top">--</td>
<td width="38" valign="top">--</td>
<td width="11" valign="top"></td>
</tr>
<tr>
<td width="63" valign="top">SQLite</td>
<td width="68" valign="top">3948</td>
<td width="42" valign="top">3171</td>
<td width="38" valign="top">2355</td>
<td width="11" valign="top">3480</td>
</tr>
<tr>
<td width="63" valign="top">UltraLite</td>
<td width="68" valign="top">8780</td>
<td width="42" valign="top">6651</td>
<td width="38" valign="top">5747</td>
<td width="11" valign="top">6683</td>
</tr>
<tr>
<td width="63" valign="top">SQLCE</td>
<td width="68" valign="top">5618</td>
<td width="42" valign="top">6113</td>
<td width="39" valign="top">5365</td>
<td width="13" valign="top">7079</td>
</tr>
</tbody></table>
Here you see again, SQLite as run into the lead.  I would also say that UltraLite and SQLCE give a very respectable showing.
<h2>Database size</h2>
These are mobile devices, space is very limited.  You laptop toting developer all want to talk about gigabytes,  I’m happy to be talking about megabytes in tens – not even hundreds.  So final database size is important.
<table border="0" cellspacing="0" cellpadding="2" width="222">
<tbody>
<tr>
<td width="74" valign="top">Perst</td>
<td width="146" valign="top">408k *</td>
</tr>
<tr>
<td width="74" valign="top">SQLite</td>
<td width="146" valign="top">333k</td>
</tr>
<tr>
<td width="74" valign="top">UltraLite</td>
<td width="146" valign="top">480k</td>
</tr>
<tr>
<td width="74" valign="top">SQLCE</td>
<td width="146" valign="top">640k</td>
</tr>
</tbody></table>
<em>* Incomplete result</em>

Because I did not complete the Perst tests, take that number with a grain of salt.  All of the other are reasonably accurate though.  Amazingly, SQLite came out ahead again.
<h2>Conclusion</h2>
Again, these are not conclusive tests.  Mileage may vary, other factors may apply in choosing one over the other.  But, if you don’t have a synchronizing application, or you are willing to handle that yourself, then SQLite is an excellent option.  If you are willing to go non-conventional for even more speed, then Perst looks to have some good advantages as well.

SQLite also is not issue free.  One problem I encountered from time to time was a “Database locked” error.  I usually got this when executing large numbers of transactions.  As luck would have it, I got a new Ado.Net Provider (065) and the problem went away.

I will also throw out some reasons for Ultalite while I’m at it.  UltaLite has an excellent sync engine to go with it, and also includes device management software.  A downside it that UltraLite is the one database you can not deploy for free.  (Hopefully, in the near future we will also have some tests for Sybase SQLAnywhere as well, it is a more powerful database than UltraLite, but is also non-free).

Some defense for SQLCE.  SQLCE actually has some very good integration with SQL Server, including some of the new column date/time types from SQL Server 2008, as well as a serviceable synchronization engine in Microsoft Sync Services.  Unfortunately, I can’t whole heartedly get behind it – even the Sync Framework for Devices is still in CTP.  The main reason to go with SQLCE is because the SQL used in SQLCE is closest to what is used in SQL Server (or you have a client that insists).  Either way, there is technically wrong with SQL CE.

As for Perst, it is just too knew for me yet.  I’ll have to do a post on how you interact with the api, for instance, as it is not an Ado.Net provider.  But the performance for most tests was very good.  I just have to play with the API a bit more.  Also, the most glowing thing I can say about Perst, the Perst team has been EXTREEMLY responsive to requests.]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/08/24/mobile-db-performance-testing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Repost: Watch out for SQL Server Parameter Sniffing</title>
		<link>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=repost-watch-out-for-sql-server-parameter-sniffing</link>
		<comments>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 16:38:00 +0000</pubDate>
		<dc:creator>Chris Brandsma</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/</guid>
		<description><![CDATA[I posted on this about a year ago.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA). Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/">I posted on this about a year ago</a>.&#160; I am reposting this as a Public Service Announcement (otherwise known as a PSA).</p>  <p>Do you have a stored procedure where the amount of data returned can vary wildly depending on what parameters are passed in?&#160; Does performance change dramatically depending on how much data is being returned?&#160; You could be a victim of SQL Server Parameter sniffing.</p>  <p>Luckily there is an easy fix that doesn’t involve medication…but you might have to change some of your code, just a little bit.</p>  <p>Take your standard stored procedure:</p>  <div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">   <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">     <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>     <span style="color: #0000ff">WHERE</span> UserName = @UserName</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span> END</pre>
  </div>
</div>

<p>And make the following (highlighted) changes.</p>

<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
  <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">CREATE</span> <span style="color: #0000ff">PROCEDURE</span> GetUserData</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>     @UserName nvarchar(20)</pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span> <span style="color: #0000ff">AS</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span> <span style="color: #0000ff">BEGIN</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>     <span style="background-color: yellow; color: black"><span style="color: black">DECLARE</span> @myUserName nvarchar(20)</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>      <span style="background-color: yellow; color: black"><span style="color: black">SET</span> @myUserName = @UserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>&#160; </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>     <span style="color: #0000ff">SELECT</span> DisplayName, FirstName, LastName </pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>     <span style="color: #0000ff">FROM</span> dbo.<span style="color: #0000ff">User</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>     <span style="color: #0000ff">WHERE</span><span style="background-color: yellow"> UserName = @myUserName</span></pre>

    <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span> END</pre>
  </div>
</div>

<p>Also note: if you read through the links of my previous post, you will see this issue affects more than just SQL Server.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/06/24/repost-watch-out-for-sql-server-parameter-sniffing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Stored Procedure Patterns</title>
		<link>http://elegantcode.com/2009/01/25/stored-procedure-patterns/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stored-procedure-patterns</link>
		<comments>http://elegantcode.com/2009/01/25/stored-procedure-patterns/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 04:48:47 +0000</pubDate>
		<dc:creator>Tony Rasa</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/25/stored-procedure-patterns/</guid>
		<description><![CDATA[Everybody loves stored procedures.&#160; Over time, I've found that some common patterns emerge in stored procedure design.&#160; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&#160; I hope you enjoy these Straw Men, because they were fun to put together.&#160; The OBJECT RETRIEVAL Patterncreate proc GetOrder(@orderId int) AS SELECT * [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody loves stored procedures.&nbsp; Over time, I've found that some common patterns emerge in stored procedure design.&nbsp; These are a few of my favorites, mostly rendered obsolete by modern ORM technology.&nbsp; I hope you enjoy these Straw Men, because they were fun to put together.&nbsp; </p> <h3>The OBJECT RETRIEVAL Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetOrder(@orderId <span class="kwrd">int</span>)
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @orderId</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>This is a very simple form of the pattern.&nbsp; In more advanced DBA-driven shops, this procedure might be auto-generated off of some master Entity-Relation diagram, and perhaps would include other information joined in that could, possibly, be useful under one or more situations.&nbsp; A common example is joining to the Users table so you can pull in "CreatedByUserName."&nbsp; Auto-generating takes all the fun out of maintaining stored procedures, so most DBAs don't go that route.&nbsp; </p>
<p>The behavior this procedure holds is easily dealt with by any ORM you care to deal with, without any effort at all.</p>
<h3>The LOOKUP Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> GetProductTypes
<span class="kwrd">AS</span>
    <span class="kwrd">SELECT</span> ProductTypeID, ProductTypeName 
    <span class="kwrd">FROM</span> ProductTypes 
    <span class="kwrd">ORDER</span> <span class="kwrd">BY</span> ProductTypeName</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<p>Very similar to retrieval, this pattern is used to return that list of Name/Value pairs typically used to needed to populate a drop down list.&nbsp; Encoding ordering details specific to the UI is common, more complex versions allow ordering to be defined by parameter or provide multiple copies of the stored procedure, ex. GetProductTypesOrderedByID, GetProductTypesOrderedByDate, ...</p>
<p>As with the OBJECT RETRIEVAL pattern, any ORM can deal with this easily.&nbsp; No reason to write this stored procedure, either.&nbsp; </p>
<h3>The UPSERT Pattern</h3><pre class="csharpcode"><span class="kwrd">create</span> <span class="kwrd">proc</span> InsertOrUpdateOrder(
    @id <span class="kwrd">int</span>,
    @name nvarchar(50),
    [more <span class="kwrd">parameters</span>...]
) <span class="kwrd">AS</span>
    <span class="kwrd">IF</span> <span class="kwrd">EXISTS</span>(<span class="kwrd">SELECT</span> * <span class="kwrd">FROM</span> Orders <span class="kwrd">WHERE</span> OrderId = @id)
    <span class="kwrd">BEGIN</span>
        <span class="kwrd">UPDATE</span> Orders <span class="kwrd">SET</span> (...) <span class="kwrd">WHERE</span> OrderId = @id
    <span class="kwrd">ELSE</span>
        INSERT <span class="kwrd">INTO</span> Orders <span class="kwrd">VALUES</span> (...)
    END</pre>
<p>Everybody's favorite stored procedure, usually contains some sort of primitive error checking, and also returns the value of the newly created OrderID if applicable.&nbsp; This type of procedure is (could be) commonly auto-generated, as there really isn't much to think about here.&nbsp; This is of course an overly simplistic form - better versions use a more intelligent check for existence.&nbsp; This is such a common pattern that more advanced databases include a special UPSERT keyword to handle it.</p>
<p>Yeah ORMs handle this one easily too.&nbsp; Bonus: business validation can be moved from your stored procedure where you can't easily test it and have to deal with change management. Instead put that logic into imperative code where it belongs.</p>
<h3>The BUSINESS LOGIC Pattern</h3>
<p>This procedure is much more complicated than the others, encapsulating large amounts of logic into a language format that doesn't lend itself to imperative statements. Some typical examples are handling things like CALCULATE_SALES_TAX or determining which is the most efficient shipping mechanism to fulfill an order.&nbsp; Another common business logic procedure uses string contatenation (and a lot of string concatenation) to send emails via xp_send_mail.&nbsp; </p>
<p>These procedures span hundreds or thousands of lines of dense and imperative-style SQL. (I'd provide an example, but I think there is a size limit to how big a blog post can be here.)&nbsp; </p>
<p>Does the procedure work?&nbsp; Well, an answer comes out of it...for goodness sake DON'T CHANGE ANYTHING or you'll crash the entire inventory subsystem!</p>
<p>All of the other stored procedure patterns are a nuisance, but typically not dangerous.&nbsp; This one is a monster.&nbsp; Common problems are finding that an exception occurs early in the procedure and wasn't handled correctly, resulting in a false answer.&nbsp; Or, there's a conditional that is always true somewhere around line 30, so the other 3000 lines of code are never executed.&nbsp; Good times :)</p>
<p>Replace these with code under test, as soon as you can.&nbsp; </p>
<h3>The SET OPERATION Pattern</h3>
<p>This procedure uses SQL to operate on sets of data, cleanly specifying what sort of transform is supposed to happen and what the resulting set of data will look like.&nbsp; This could be fancy and use MDX to operate on cubes of data, or more commonly takes complex data structures and maps them against something simpler to fulfill a specific need.</p>
<p>Of course, ORMs can...hey wait a minute, this is the one where we're playing to the stored procedure's strength!&nbsp;&nbsp; Too bad these procedures are so rare...</p>
<p>&nbsp;</p>
<p>I hope you enjoyed this attempt to troll out all the DBAs in the audience. :)</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/25/stored-procedure-patterns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL Window Clause</title>
		<link>http://elegantcode.com/2009/01/04/sql-window-clause/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-window-clause</link>
		<comments>http://elegantcode.com/2009/01/04/sql-window-clause/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:46:31 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2009/01/04/sql-window-clause/</guid>
		<description><![CDATA[Hi it's Jason again. I enjoyed writing my last post on SQL pivot so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause. As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such [...]]]></description>
			<content:encoded><![CDATA[<p>Hi it's Jason again. I enjoyed writing my <a href="http://elegantcode.com/2008/12/12/sql-pivot/">last post on SQL pivot</a> so much that today I thought that I would explore another rarely used feature of this ubiquitous query language - the window clause.</p>  <p>As before I am using SQL Anywhere 10 but the same technique will work with several modern databases such as Oracle or to a limited extent (with 2005 anyway, it only supports the <em>partition by</em> clause in ranking functions) SQL Server. Let's start with some test data:</p>  <p>create table orders (order_dt datetime, total int, customer_id int) </p>  <p>insert into orders values ('2008-01-01', 50, 1)   <br />insert into orders values ('2008-01-02', 100, 2)    <br />insert into orders values ('2008-01-10', 75, 3)    <br />insert into orders values ('2008-01-11', 65, 1)    <br />insert into orders values ('2008-01-12', 85, 2)    <br />insert into orders values ('2008-02-01', 39, 1) </p>  <p>Now execute the following SQL:</p>  <p>select   <br />&#160; customer_id,    <br />&#160; order_dt,    <br />&#160; total,    <br />&#160; sum(total) over (partition by customer_id order by order_dt) running_total    <br />from orders    <br />order by    <br />&#160; customer_id,    <br />&#160; order_dt</p>  <p>You'll see that a running total is displayed for the each customer's orders. Examining the SQL what might look a little unusual is the <em>over</em> keyword and what follows it inside the parenthesis. This is the window clause and there are zero, one or two parts to it. The <em>partition by</em> syntax allows you to create a group within the selected data. And the <em>order by</em> clause rather unsurprisingly allows you to order the results. Also note how you are able to perform aggregation in a scenario when there is none. The possibilities here are endless.</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2009/01/04/sql-window-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Pivot</title>
		<link>http://elegantcode.com/2008/12/12/sql-pivot/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sql-pivot</link>
		<comments>http://elegantcode.com/2008/12/12/sql-pivot/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 19:02:09 +0000</pubDate>
		<dc:creator>Jason Grundy</dc:creator>
				<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://elegantcode.com/2008/12/12/sql-pivot/</guid>
		<description><![CDATA[This is Jason who is continuing to masquerade as a guest. I'm going to let you into a dirty little secret...I've written a lot of SQL during my career. This admission almost sounds like heresay in these days of DDD, BDD etc. but it's still an incredibly useful skill to have. Anyway a lot of [...]]]></description>
			<content:encoded><![CDATA[<p>This is Jason who is continuing to masquerade as a guest.</p>  <p>I'm going to let you into a dirty little secret...I've written a lot of SQL during my career. This admission almost sounds like heresay in these days of DDD, BDD etc. but it's still an incredibly useful skill to have. Anyway a lot of our development is performed in an environment where OR/M tools such as NHibernate are not an option so we need to rely on such traditional techniques more often than I would like.</p>  <p>Today someone came to me and said &quot;So I have a route. And a route can have jobs. And each job has a status. I need to show for each route the number of jobs that have a particular status and which don't have the status&quot;.</p>  <p>What they are really asking for is to pivot the data - the rows need to be converted to columns. The technique that I employed to solve this problem uses a combination of a case statement and an aggregate function to pivot the data. More explicitly the case statement is used to bucket the data and the aggregate function to do something to that bucket. Normally I would use a COUNT but the RDBMS in question (SQL Anywhere) throws a warning when a null is aggregated so I used SUM instead.</p>  <p>What was interesting when I looked at how I presented my solution to my colleague was that the format is not too dissimilar to what I might do with a more fully featured language than SQL (yes I know there's no tests but it's pretty close to a specification as it's a paint by numbers solution). Anyway here's the SQL:</p>  <p>create table route (id int) </p>  <p>create table job (id int, route_id int, status varchar(1)) </p>  <p>insert into route (id) values (1)    <br />insert into route (id) values (2) </p>  <p>insert into job (id, route_id, status) values (1, 1, 'A')    <br />insert into job (id, route_id, status) values (2, 1, 'B')     <br />insert into job (id, route_id, status) values (3, 1, 'A')     <br />insert into job (id, route_id, status) values (4, 2, 'A')     <br />insert into job (id, route_id, status) values (4, 2, 'B')     <br />insert into job (id, route_id, status) values (5, 2, 'C') </p>  <p>select    <br />&#160; route_id,     <br />&#160; sum(case when status = 'A' then 1 else 0 end) sum_a,     <br />&#160; sum(case when status &lt;&gt; 'A' then 1 else 0 end) sum_not_a     <br />from     <br />&#160; route r     <br />&#160; inner join job j on r.id = j.route_id     <br />group by     <br />&#160; route_id     <br />order by     <br />&#160; route_id</p>]]></content:encoded>
			<wfw:commentRss>http://elegantcode.com/2008/12/12/sql-pivot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

