<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://consultingblogs.emc.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Andrew Clancy's Blog</title><link>http://consultingblogs.emc.com/andrewclancy/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2.1 SP3 (Build: 20423.1)</generator><item><title>NHibernate Query Generator in Action</title><link>http://consultingblogs.emc.com/andrewclancy/archive/2008/10/10/nhibernate-query-generator-in-action.aspx</link><pubDate>Fri, 10 Oct 2008 10:07:40 GMT</pubDate><guid isPermaLink="false">e847c0e7-38d9-45c0-b593-56747303e088:12752</guid><dc:creator>Andrew.Clancy</dc:creator><slash:comments>5</slash:comments><comments>http://consultingblogs.emc.com/andrewclancy/comments/12752.aspx</comments><wfw:commentRss>http://consultingblogs.emc.com/andrewclancy/commentrss.aspx?PostID=12752</wfw:commentRss><description>&lt;p&gt;NHibernate querying is great – it gives us the ability to query objects directly without the need to know anything about the underlying relational schema. It has a couple of major flaws though: 1. property names are accessed via strings, so we don’t know until runtime whether they exist, or are mapped 2. it’s ugly and cumbersome – frankly probably one of the major barriers I’ve had to ORM until now. &lt;/p&gt;  &lt;p&gt;Ayende’s &lt;a href="http://www.google.co.uk/search?q=site:www.ayende.com+NHibernate+Query+Generator+1."&gt;NHibernate Query Generator&lt;/a&gt; fixes both of these things. Mapped properties are accessed via properties as nature intended, and querying is a lot easier to read and write. Not quite as neat as Linq-to-NHibernate will be, but so much better than native NHibernate querying that I wonder why it wasn’t included in the trunk. &lt;/p&gt;  &lt;p&gt;Having said that – here’s why you shouldn’t wait for the linq version if you’re doing loads of NHib querying right now. The following checks for city &amp;amp; state in a person’s address using native NHibernate criteria - note especially the strings for property names if not the unreadable syntax &amp;amp; subquery. &lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;DetachedCriteria addressCrit = DetachedCriteria.For&amp;lt;Address&amp;gt;()            &lt;br /&gt;.SetProjection(Projections.Id())             &lt;br /&gt;.Add(Restrictions.Like(&lt;b&gt;“City”&lt;/b&gt;, &amp;quot;Brisbane&amp;quot;, MatchMode.Anywhere)             &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; || Restrictions.Eq(&lt;b&gt;“State”&lt;/b&gt;, &amp;quot;NSW&amp;quot;));             &lt;br /&gt;DetachedCriteria personQuery = DetachedCriteria.For&amp;lt;Person&amp;gt;()             &lt;br /&gt;.CreateCriteria(&lt;b&gt;“Addresses”&lt;/b&gt;)             &lt;br /&gt;.Add(&lt;b&gt;Subqueries.PropertyIn(&amp;quot;ID&amp;quot;, addressCrit)&lt;/b&gt;);&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;I reckon the NHQG version speaks for itself: &lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Person.Addresses .Add(Where.Address.City.Contains(&amp;quot;Brisbane&amp;quot;)            &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; || Where.Address.State == &amp;quot;NSW&amp;quot;)&lt;/font&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Most of the stuff you’d hope for is in the NHQG.    &lt;br /&gt;All of the NHibernate functions are there (including ordering, aggregates etc), eg:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Order.StatusID.InG(statusList);&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Including chaining: &lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Address.City.Contains(&amp;quot;Brisbane&amp;quot;)            &lt;br /&gt;|| Where.Address.State == &amp;quot;NSW&amp;quot;) // &amp;amp;&amp;amp; works too&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Loads of expressions are overloaded:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Comment.RecordedDate &amp;lt;= endDate // ==, !=, &amp;lt;, &amp;lt;=, &amp;gt;, &amp;gt;=, &amp;amp;&amp;amp;, ||, &amp;amp;=, |=&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;If you need a property of a property (to any level) you’ve got it:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Person.PhoneNumber.AreaCode.StartsWith(“02”) // Like, Contains&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&lt;em&gt;I’ve sent Ayende a NHQGH patch for a few of my own additions&lt;/em&gt; – here’s where these start … &lt;/p&gt;  &lt;p&gt;If you don’t have a mapping between properties, matching is still easy:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="10" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Address.CountryID.Matches(Where.Country.Name.Contains(value))&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;That’ll match using Address.CountryID. Another match, this time using a different match id on the target:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Person.Matches(Get.KnownAs.PersonID,            &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Where.KnownAs.IsKnownAs.Contains(forename))&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Like/Contains/Starts with on lists:&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Person.Bio.ContainsList(new List&amp;lt;string&amp;gt;{“zodie”, “loves”, “nhqg”})&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;This is built using the To*Junction() extension methods: &lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;keywords.Select(s =&amp;gt; Where.Person.Bio.Contains(s)).ToDisjunction()&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;You can of course mix &amp;amp; match with standard NHibernate criteria, but pretty much everything I’ve found sofar is do-able using pure NHQG.&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="8" width="655" border="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;font face="Courier New"&gt;Where.Person.Addresses.Add(            &lt;br /&gt;Restrictions.Eq(Get.Address.Town.Like(“Brisbane”, MatchMode.Anywhere)&lt;/font&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;So, the key is here that all of your querying can now be done using properties on the NHQG rather than strings, allowing you to validate changes to your objects &amp;amp; mappings at compile time, rather than when you run your unit tests. That’s a pretty quick summary, but if you’re not convinced yet I can only recommend you give it a go – I’ve just applied it on our project and we’re already feeling the time saving, and more importantly extra confidence when refactoring. &lt;/p&gt;  &lt;p&gt;The NHQG can be added to your solution as a Custom Tool so every time your mapping file is updated, the NHQG layer (it basically works by generating some C# for you) is updated. If anyone’s interested in a how-to on this, drop me a line. The NHQG can be found in &lt;a href="http://sourceforge.net/projects/rhino-tools"&gt;Rhino tools&lt;/a&gt; here, hopefully including my extensions soon! &lt;/p&gt;&lt;img src="http://consultingblogs.emc.com/aggbug.aspx?PostID=12752" width="1" height="1"&gt;</description></item></channel></rss>
