<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Random Code &#187; NHibernate</title>
	<atom:link href="http://randomcode.net.nz/category/nhibernate/feed/" rel="self" type="application/rss+xml" />
	<link>http://randomcode.net.nz</link>
	<description>Random code and concepts from yet another .NET developer</description>
	<lastBuildDate>Thu, 26 May 2011 05:24:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='randomcode.net.nz' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Random Code &#187; NHibernate</title>
		<link>http://randomcode.net.nz</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://randomcode.net.nz/osd.xml" title="Random Code" />
	<atom:link rel='hub' href='http://randomcode.net.nz/?pushpress=hub'/>
		<item>
		<title>Query Encapsulation Comes Full Circle</title>
		<link>http://randomcode.net.nz/2010/08/17/query-encapsulation-comes-full-circle/</link>
		<comments>http://randomcode.net.nz/2010/08/17/query-encapsulation-comes-full-circle/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 21:55:16 +0000</pubDate>
		<dc:creator>Neal</dc:creator>
				<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://randomcode.net.nz/?p=130</guid>
		<description><![CDATA[I&#8217;ve just about finished migrating a bunch of code from using LINQ based queries against my IRepository, which follows this approach discussed by Fabio Maulo, to enhanced query objects, which follow this pattern; again from the formidable mind of Fabio Maulo. As I was writing the queries, I realised that I was effectively encapsulating the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=130&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just about finished migrating a bunch of code from using LINQ based queries against my IRepository, which follows <a title="Repository or DAO?: Repository" href="http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html" target="_blank">this approach</a> discussed by Fabio Maulo, to enhanced query objects, which follow <a title="Enhanced Query Object" href="http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html" target="_blank">this pattern</a>; again from the formidable mind of Fabio Maulo.</p>
<p>As I was writing the queries, I realised that I was effectively encapsulating the query logic into a self contained object, which is not unlike what a stored procedure does.  So here I am, 10 years or so after I started encapsulating my queries in stored procedures and some 2 or 3 years after giving up stored procedures, encapsulating my queries again.</p>
<p><strong>But why the change?</strong></p>
<p>While LINQ queries work well in small simple cases, you rapidly come to understand that it is effectively the lowest common denominator for working with your ORM (I prefer NHibernate but it applies as well to most others).  The workaround for this is to use a bunch of extension methods meaning you end up referencing your ORM from your service layer which (rightly or wrongly) makes me feel ill.  Enhanced Query Objects allow you to leverage the native power of your ORM while proving a suitably minimalistic interface which greatly increases SoC and simplifies testing of the query consumers.  The implementation also allows the queries to be thoroughly tested in isolation without too much difficulty.</p>
<br />Filed under: <a href='http://randomcode.net.nz/category/nhibernate/'>NHibernate</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nealblomfield.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nealblomfield.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nealblomfield.wordpress.com/130/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=130&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://randomcode.net.nz/2010/08/17/query-encapsulation-comes-full-circle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Neal</media:title>
		</media:content>
	</item>
		<item>
		<title>Simplify IUserType Testing</title>
		<link>http://randomcode.net.nz/2009/10/16/simplify-iusertype-testing/</link>
		<comments>http://randomcode.net.nz/2009/10/16/simplify-iusertype-testing/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 02:08:03 +0000</pubDate>
		<dc:creator>Neal</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://randomcode.net.nz/?p=110</guid>
		<description><![CDATA[Background The application I am currently working on makes ( will make ) heavy use of the .NET TimeZoneInfo class to allow us to display times in the current users local time. To achieve this we need to capture and store the timezone from the user. Capturing the timezone is relatively simple, I use a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=110&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong><em>Background</em></strong></p>
<p>The application I am currently working on makes ( will make ) heavy use of the .NET TimeZoneInfo class to allow us to display times in the current users local time.  To achieve this we need to capture and store the timezone from the user.</p>
<p>Capturing the timezone is relatively simple, I use a slightly modified version of <a title="Automagic Time Localization" href="http://kohari.org/2009/06/15/automagic-time-localization/" target="_blank">this technique</a> used by Nate Kohari&#8217;s most excellent <a title="Zen - Online Kanban" href="http://www.agilezen.com/" target="_blank">Zen</a>.</p>
<p>Storing the timezone provides an interesting choice of options;</p>
<p>I could store the raw offset in hours ( a double ) or in minutes ( an int ) and recreate the TimeZoneInfo each time I want to display a date or time in the users local time.  This has the benefit of being incredibly simple and, with a little work to create an extension method, generates almost no duplication <em>except the act of converting the double or int into a TimeZoneInfo</em>.</p>
<p>The second alternative was to let my trusty ORM do the work for me.  I use NHibernate and after a little research I found the following articles <a title="Generic NHibernate User Type Base Class" href="http://darrell.mozingo.net/2009/02/10/generic-nhibernate-user-type-base-class/" target="_blank">about</a> <a title="implementing custom types in nhibernate" href="http://intellect.dk/post/Implementing-custom-types-in-nHibernate.aspx" target="_blank">creating</a> an <a title="Mapping different types with NHibernate - IUserType" href="http://kozmic.pl/archive/2009/10/12/mapping-different-types-with-nhibernate-iusertype.aspx" target="_blank">IUserType</a> that would allow me to map a TimeZoneInfo into a database field.  If you want all the gory details of how to do it go and read those articles, otherwise the code for my TimeZoneInfoUserType is shown at the bottom of the post ( see the section titled The Implementation ).</p>
<p><strong><em>The Useful Stuff</em></strong></p>
<p>Normally I use a BDD style approach for building something like this, but as I wasn&#8217;t sure how to solve the problem, I spiked out the approach, then added the tests and refined the implementation as required.</p>
<p>Part of spiking out the solution was figuring out how to test it and this initially tripped me up as I was considering mocking IDbCommand and IDataReader ( which gets ugly fast ).</p>
<p>After a little bit of thought, I figured I could use a SqlCommand for the IDbCommand.  The following snippet shows what you need to do to use a SqlCommand for testing your NullSafeSet ( note where parameter index comes from ).</p>
<p><pre class="brush: csharp;">
_command = new SqlCommand();
_parameterIndex = _command.Parameters.Add( _command.CreateParameter() );

// ... this is then used in the NullSafeSet test ...
_userType.NullSafeSet( _command, null, _parameterIndex );
</pre></p>
<p>To find an acceptable IDataReader stand-in, I went poking around with Reflector and found an IDataReader implementation that wraps a DataTable.  This gave me a means of quickly and easily controlling the data being passed to the code under test.  The following snippet shows how you can set up an IDataReader from a DataTable in as little as 5 lines of code for testing your NullSafeGet ( note the data reader must be &#8220;initialised&#8221; by calling Read() before using it ):</p>
<p><pre class="brush: csharp;">
var dataTable = new DataTable();
dataTable.Columns.Add( ColumnName, typeof( int ) );
dataTable.LoadDataRow( new object[] {TimezoneOffset * 60}, true );
_dataReader = new DataTableReader( dataTable );
_dataReader.Read();

// ... this is then used in the NullSafeSet test ...
_timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );
</pre></p>
<p>The full source for the TimeZoneInfoUserType and the associated tests is shown below:</p>
<p><strong><em>The Implementation</em></strong></p>
<p><pre class="brush: csharp;">
    public class TimezoneInfoUserType : IUserType
    {
        public new bool Equals(object x, object y)
        {
            if( ReferenceEquals( x, y ) )
            {
                return true;
            }
            if( x == null || y == null )
            {
                return false;
            }

            return x.Equals( y );
        }

        public int GetHashCode( object x )
        {
            return x.GetHashCode();
        }

        public object NullSafeGet( IDataReader rs, string[] names, object owner )
        {
            var rawValue = NHibernateUtil.Int32.NullSafeGet( rs, names[ 0 ] );
            if( rawValue == null )
            {
                return null;
            }
            var timezoneOffsetMinutes = (int) rawValue;
            var timezoneOffset = new TimeSpan( 0, timezoneOffsetMinutes, 0 );
            return TimeZoneInfoFactory.Create( timezoneOffset.TotalHours );
        }

        public void NullSafeSet( IDbCommand cmd, object value, int index )
        {
            if(value == null)
            {
                NHibernateUtil.Int32.NullSafeSet( cmd, null, index );
                return;
            }
            var timezoneInfo = (TimeZoneInfo) value;
            var offsetInMinutes = timezoneInfo.BaseUtcOffset.TotalMinutes;
            NHibernateUtil.Int32.NullSafeSet( cmd, Convert.ToInt32( offsetInMinutes ) , index );
        }

        public object DeepCopy( object value )
        {
            return value;
        }

        public object Replace( object original, object target, object owner )
        {
            return original;
        }

        public object Assemble( object cached, object owner )
        {
            return cached;
        }

        public object Disassemble( object value )
        {
            return value;
        }

        public SqlType[] SqlTypes
        {
            get { return new[] {SqlTypeFactory.Int32}; }
        }

        public Type ReturnedType
        {
            get { return typeof( TimeZoneInfo ); }
        }

        public bool IsMutable
        {
            get { return false; }
        }
    }
</pre></p>
<p><strong><em>The Tests</em></strong><br />
Note: If you are wondering about the =()=&gt; sequence, I use MSpec for my testing.</p>
<p><pre class="brush: csharp;">
    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_null_TimezoneInfo
    {
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;

        Establish context = () =&gt;
        {
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =&gt;
            _userType.NullSafeSet( _command, null, _parameterIndex );

        It the_offset_is_stored_as_null = () =&gt;
            ((IDataParameter)_command.Parameters[ _parameterIndex ]).Value.ShouldEqual(DBNull.Value);
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_zero_offset
    {
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =&gt;
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( 0 );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =&gt;
            _userType.NullSafeSet(_command, _timezoneInfo, _parameterIndex);

        It the_offset_is_stored_as_zero = () =&gt;
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( 0 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_positive_offset
    {
        const int TimezoneOffset = 12;
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =&gt;
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( TimezoneOffset );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =&gt;
            _userType.NullSafeSet( _command, _timezoneInfo, _parameterIndex );

        It the_offset_is_stored_in_minutes = () =&gt;
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( TimezoneOffset * 60 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_saving_a_TimezoneInfo_with_a_negative_offset
    {
        const int TimezoneOffset = -12;
        static int _parameterIndex;
        static TimezoneInfoUserType _userType;
        static IDbCommand _command;
        static TimeZoneInfo _timezoneInfo;

        Establish context = () =&gt;
        {
            _timezoneInfo = TimeZoneInfoFactory.Create( TimezoneOffset );
            _userType = new TimezoneInfoUserType();
            _command = new SqlCommand();
            _parameterIndex = _command.Parameters.Add( _command.CreateParameter() );
        };

        Because of = () =&gt;
            _userType.NullSafeSet( _command, _timezoneInfo, _parameterIndex );

        It the_offset_is_stored_in_minutes = () =&gt;
            ( (IDataParameter) _command.Parameters[ _parameterIndex ] ).Value.ShouldEqual( TimezoneOffset * 60 );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_null_TimezoneInfo
    {
        const string ColumnName = &quot;Timezone&quot;;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =&gt;
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {null}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =&gt;
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It returns_null = () =&gt;
            _timezoneInfo.ShouldBeNull();
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_zero_offset
    {
        const string ColumnName = &quot;Timezone&quot;;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =&gt;
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {0}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =&gt;
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It the_BaseUtcOffset_is_zero = () =&gt;
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( 0d );

        It the_displayname_is_GMT = () =&gt;
            _timezoneInfo.DisplayName.ShouldEqual( &quot;GMT&quot; );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_positive_offset
    {
        const string ColumnName = &quot;Timezone&quot;;
        const int TimezoneOffset = 12;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =&gt;
        {
        _userType = new TimezoneInfoUserType();
        var dataTable = new DataTable();
        dataTable.Columns.Add(ColumnName, typeof(int));
        dataTable.LoadDataRow(new object[] { TimezoneOffset * 60 }, true);
        _dataReader = new DataTableReader(dataTable);
        _dataReader.Read();
        };

        Because of = () =&gt;
            _timezoneInfo = (TimeZoneInfo)_userType.NullSafeGet(_dataReader, new[] { ColumnName }, null);

        It the_BaseUtcOffset_is_generated_from_the_number_of_minutes_retrieved = () =&gt;
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( TimezoneOffset );

        It the_displayname_follows_the_pattern_GMT_plus_timezone_offset_ = () =&gt;
            _timezoneInfo.DisplayName.ShouldEqual( &quot;GMT+&quot; + TimezoneOffset );
    }

    [Subject(typeof(TimezoneInfoUserType))]
    public class When_retrieving_a_TimezoneInfo_with_a_negative_offset
    {
        const string ColumnName = &quot;Timezone&quot;;
        const int TimezoneOffset = -12;
        static TimeZoneInfo _timezoneInfo;
        static TimezoneInfoUserType _userType;
        static IDataReader _dataReader;

        Establish context = () =&gt;
        {
            _userType = new TimezoneInfoUserType();
            var dataTable = new DataTable();
            dataTable.Columns.Add( ColumnName, typeof( int ) );
            dataTable.LoadDataRow( new object[] {TimezoneOffset * 60}, true );
            _dataReader = new DataTableReader( dataTable );
            _dataReader.Read();
        };

        Because of = () =&gt;
            _timezoneInfo = (TimeZoneInfo) _userType.NullSafeGet( _dataReader, new[] {ColumnName}, null );

        It the_BaseUtcOffset_is_generated_from_the_number_of_minutes_retrieved = () =&gt;
            _timezoneInfo.BaseUtcOffset.TotalHours.ShouldEqual( TimezoneOffset );

        It the_displayname_follows_the_pattern_GMT_minus_timezone_offset_ = () =&gt;
            _timezoneInfo.DisplayName.ShouldEqual( &quot;GMT&quot; + TimezoneOffset );
    }
</pre></p>
<br />Posted in NHibernate, TDD, Unit Testing  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nealblomfield.wordpress.com/110/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nealblomfield.wordpress.com/110/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nealblomfield.wordpress.com/110/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=110&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://randomcode.net.nz/2009/10/16/simplify-iusertype-testing/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Neal</media:title>
		</media:content>
	</item>
		<item>
		<title>NHibernate Lambda Extentions Gotcha</title>
		<link>http://randomcode.net.nz/2009/03/04/nhibernate-lambda-extentions-gotcha/</link>
		<comments>http://randomcode.net.nz/2009/03/04/nhibernate-lambda-extentions-gotcha/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 19:59:38 +0000</pubDate>
		<dc:creator>Neal</dc:creator>
				<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[NHibernate Lambda Extensions]]></category>

		<guid isPermaLink="false">http://randomcode.net.nz/?p=66</guid>
		<description><![CDATA[Recently I came across the open source NHibernate Lambda Extensions project on Google Code.  This small library provides a set of extension to remove the magic strings from your NHibernate criteria queries, and it&#8217;s great (once you get used to the conventions). I&#8217;ve been slowly migrating queries across to use NHLambda and tripped up on [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=66&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Recently I came across the open source <a title="NHibernate Lambda Extentions Code" href="http://code.google.com/p/nhlambdaextensions/" target="_blank">NHibernate Lambda Extensions</a> project on Google Code.  This small library provides a set of extension to remove the magic strings from your NHibernate criteria queries, and it&#8217;s great (once you get used to the conventions).</p>
<p>I&#8217;ve been slowly migrating queries across to use NHLambda and tripped up on the following query which is effectively Survey.Status == Complete and Survey.Questionnaire.Id = questionnaireId.</p>
<p><pre class="brush: csharp;">

            var expected = DetachedCriteria.For&lt;Survey&gt;()
                .Add( Restrictions.Eq( &quot;Status&quot;, SurveyStatus.Complete ) )
                .Add( Restrictions.Eq( &quot;Questionnaire.Id&quot;, questionnaireId ) )
                .CreateAlias( &quot;Answers&quot;, &quot;answerAlias&quot; )
                .SetProjection( Projections.Property( &quot;answerAlias.Id&quot; ) );

</pre></p>
<p>Initially I had converted it as</p>
<p><pre class="brush: csharp;">

            Answer answerAlias = null;
            var actual = DetachedCriteria.For&lt;Survey&gt;()
                .Add&lt;Survey&gt;( s =&gt; s.Status == SurveyStatus.Complete )
                .Add&lt;Questionnaire&gt;( q =&gt; q.Id == questionnaireId )
                .CreateAlias&lt;Survey&gt;( s =&gt; s.Answers, () =&gt; answerAlias )
                .SetProjection( LambdaProjection.Property( () =&gt; answerAlias.Id ) );

</pre></p>
<p>which actually generates a query equivalent to Survey.Status == Complete and Survey.Id == questionnaireId.</p>
<p>After kicking myself for being lazy and not writing a test first, I wrote a test and realised that I had implicitly traversed an association in the second restriction.  There are two ways to solve this, either explicitly create the alias, or (as I have just considered and tested while writing this post) correctly place the restriction on the survey and navigate to Questionnaire.Id.  Both approaches are shown below.</p>
<p><pre class="brush: csharp;">

            // Explicitly create and navigate the alias
            Questionnaire questionnaireAlias = null;
            Answer answerAlias = null;
            var actual = DetachedCriteria.For&lt;Survey&gt;()
                .Add&lt;Survey&gt;( s =&gt; s.Status == SurveyStatus.Complete )
                .CreateAlias&lt;Survey&gt;( s =&gt; s.Questionnaire, () =&gt; questionnaireAlias )
                .Add( () =&gt; questionnaireAlias.Id == questionnaireId )
                .CreateAlias&lt;Survey&gt;( s =&gt; s.Answers, () =&gt; answerAlias )
                .SetProjection( LambdaProjection.Property( () =&gt; answerAlias.Id ) );

            // Apply the restriction to Survey and navigate to Questionnaire.Id
            var actual2 = DetachedCriteria.For&lt;Survey&gt;()
                .Add&lt;Survey&gt;(s =&gt; s.Status == SurveyStatus.Complete)
                .Add&lt;Survey&gt;(s =&gt; s.Questionnaire.Id == questionnaireId)
                .CreateAlias&lt;Survey&gt;(s =&gt; s.Answers, () =&gt; answerAlias)
                .SetProjection(LambdaProjection.Property(() =&gt; answerAlias.Id));

</pre></p>
<p>I don&#8217;t know which one of these is more correct (or even if one is better that the other), but they both look a hell of a lot better than the original with it&#8217;s many magic strings.</p>
<p>Anyway, the moral of this story is twofold; one, beware implicit association traversals when migrating queries to NHLambda and two, don&#8217;t be a clown &#8211; write unit tests to cover the migrated queries!  =)</p>
<br />Posted in NHibernate, NHibernate Lambda Extensions  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nealblomfield.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nealblomfield.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nealblomfield.wordpress.com/66/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=66&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://randomcode.net.nz/2009/03/04/nhibernate-lambda-extentions-gotcha/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Neal</media:title>
		</media:content>
	</item>
		<item>
		<title>NHibernate many-to-many mappings and order-by</title>
		<link>http://randomcode.net.nz/2009/02/03/nhibernate-many-to-many-mappings-and-order-by/</link>
		<comments>http://randomcode.net.nz/2009/02/03/nhibernate-many-to-many-mappings-and-order-by/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 20:22:29 +0000</pubDate>
		<dc:creator>Neal</dc:creator>
				<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://randomcode.net.nz/?p=44</guid>
		<description><![CDATA[Update: Frederico Tolomei has pointed out that this now works as you would expect if you place the order by on the many-to-many tag like this: Just found this and it took me a while to figure out so posting here to remind myself as well as help anyone else who stumbles over the issue. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=44&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Update</strong>:  Frederico Tolomei has pointed out that this now works as you would expect if you place the order by on the many-to-many tag like this:<br />
<pre class="brush: xml;">
    &lt;bag name=&quot;SelectedOptions&quot; cascade=&quot;none&quot; lazy=&quot;false&quot;&gt;
      &lt;key column=&quot;Answer&quot; /&gt;
      &lt;many-to-many column=&quot;AnswerOption&quot; class=&quot;AnswerOption&quot;  order-by=&quot;DisplayIndex asc&quot;/&gt;
    &lt;/bag&gt;
</pre></p>
<p>Just found this and it took me a while to figure out so posting here to remind myself as well as help anyone else who stumbles over the issue.</p>
<p>When you configure collection mappings in NHibernate, you can add an order-by attribute and specify the field to order the collection by as well as whether to sort ascending or descending.</p>
<p>With one-to-many mappings, the field you specify is a member of the entity contained in the collection so the following would contain a collection of Question instances sorted by DisplayIndex.</p>
<p><pre class="brush: xml;">
&lt;bag name=&quot;Questions&quot; cascade=&quot;all&quot; order-by=&quot;DisplayIndex asc&quot; lazy=&quot;false&quot; fetch =&quot;subselect&quot;&gt;
   &lt;key column=&quot;QuestionnaireSection&quot; /&gt;
      &lt;one-to-many class=&quot;Question&quot; /&gt;
    &lt;/bag&gt;
</pre></p>
<p>However, if the mapping is a many-to-many, the order by clause is applied to the association table &#8211; the table in the middle of a many-to-many association mapped into a relational database. I cannot use the order-by attribute on the following collection mapping.</p>
<p><pre class="brush: xml;">
    &lt;bag name=&quot;SelectedOptions&quot; cascade=&quot;none&quot; lazy=&quot;false&quot;&gt;
      &lt;key column=&quot;Answer&quot; /&gt;
      &lt;many-to-many column=&quot;AnswerOption&quot; class=&quot;AnswerOption&quot; /&gt;
    &lt;/bag&gt;
</pre></p>
<p>The implementation of this may be erroneous (and could be argued as counter-intuitive), however as it stands the order-by clause of a collection mapped as a many-to-many is not overly useful as we cannot sort a collection of entities in the same manner as we can with a many-to-one mapping.</p>
<br />Posted in NHibernate  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nealblomfield.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nealblomfield.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nealblomfield.wordpress.com/44/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=44&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://randomcode.net.nz/2009/02/03/nhibernate-many-to-many-mappings-and-order-by/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Neal</media:title>
		</media:content>
	</item>
		<item>
		<title>Restricting types returned from a polymorphic query</title>
		<link>http://randomcode.net.nz/2008/09/19/restricting-types-returned-from-a-polymorphic-query/</link>
		<comments>http://randomcode.net.nz/2008/09/19/restricting-types-returned-from-a-polymorphic-query/#comments</comments>
		<pubDate>Thu, 18 Sep 2008 20:03:15 +0000</pubDate>
		<dc:creator>Neal</dc:creator>
				<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://nealblomfield.wordpress.com/?p=37</guid>
		<description><![CDATA[NHibernate is cool, I can map an inheritance hierarchy into my database, ask it to get me all instances of an object at the root of the hierarchy and NHibernate will automatically retrieve all subclasses and instantiate the actual (derived) type.  What does this mean in practice? If I have the following class hierarchy and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=37&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>NHibernate is cool, I can map an inheritance hierarchy into my database, ask it to get me all instances of an object at the root of the hierarchy and NHibernate will automatically retrieve all subclasses and instantiate the actual (derived) type.  What does this mean in practice?</p>
<div id="attachment_40" class="wp-caption alignright" style="width: 310px"><a href="http://nealblomfield.files.wordpress.com/2008/09/demo-class-hierarchy.png"><img class="size-medium wp-image-40" title="demo-class-hierarchy" src="http://nealblomfield.files.wordpress.com/2008/09/demo-class-hierarchy.png?w=300&#038;h=169" alt="Demo class hierarchy" width="300" height="169" /></a><p class="wp-caption-text">Demo class hierarchy</p></div>
<p>If I have the following class hierarchy and I query</p>
<p>&#8220;from Animal&#8221;</p>
<p>I will get a list of Animal instances back, but looking at the type of each returned instance will show that they are either Cocker Spaniel or West Highland Terrier.</p>
<p>For the most part, this behaviour is exactly what you need to leverage polymorphism in your design, however on the odd occasion, you need to limit the returned type from a polymorphic query (in my case it was to build a report).  To achieve this you need to leverage the class meta-property and change your query to</p>
<p>&#8220;from Animal pet where pet.class = Cocker Spaniel&#8221;</p>
<p>The key to remember when using class is that you must reference it from the alias you assign to the type you want to restrict (e.g. pet in this example).</p>
<br />Posted in NHibernate  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/nealblomfield.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/nealblomfield.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/nealblomfield.wordpress.com/37/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=randomcode.net.nz&amp;blog=2728728&amp;post=37&amp;subd=nealblomfield&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://randomcode.net.nz/2008/09/19/restricting-types-returned-from-a-polymorphic-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Neal</media:title>
		</media:content>

		<media:content url="http://nealblomfield.files.wordpress.com/2008/09/demo-class-hierarchy.png?w=300" medium="image">
			<media:title type="html">demo-class-hierarchy</media:title>
		</media:content>
	</item>
	</channel>
</rss>
