<?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>Arrange Act Assert &#187; NHibernate</title> <atom:link href="http://www.arrangeactassert.com/category/nhibernate/feed/" rel="self" type="application/rss+xml" /><link>http://www.arrangeactassert.com</link> <description>Jag Reehal on Agile Development, ASP.NET MVC and all manner of good stuff</description> <lastBuildDate>Thu, 24 Nov 2011 00:01:20 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>Why I use the NHibernate Profiler for optimal ORM performance</title><link>http://www.arrangeactassert.com/why-i-use-the-nhibernate-profiler-for-optimal-orm-performance/</link> <comments>http://www.arrangeactassert.com/why-i-use-the-nhibernate-profiler-for-optimal-orm-performance/#comments</comments> <pubDate>Mon, 05 Sep 2011 23:01:41 +0000</pubDate> <dc:creator>Jag Reehal</dc:creator> <category><![CDATA[Entity Framework]]></category> <category><![CDATA[NHibernate]]></category><guid
isPermaLink="false">http://www.arrangeactassert.com/?p=1960</guid> <description><![CDATA[In this post I want to show how the NHibernate Profiler can help you avoid ORM performance issues as discussed in the post &#8216;ORMs don’t kill databases. Developers do.&#8216;. While it&#8217;s not open source it&#8217;s definitely worth the investment if you use NHibernate because it can give you alerts about any potential issues and information [...]]]></description> <content:encoded><![CDATA[<p>In this post I want to show how the <a
href="http://nhprof.com/" title="NHibernate Profiler">NHibernate Profiler</a> can help you avoid ORM performance issues as discussed in the post &#8216;<a
href="http://www.arrangeactassert.com/orms-dont-kill-databases-developers-do/" title="ORMs don’t kill databases.  Developers do.">ORMs don’t kill databases. Developers do.</a>&#8216;.</p><p>While it&#8217;s not open source it&#8217;s definitely worth the investment if you use NHibernate because it can give you alerts about any potential issues and information about how to resolve them.</p><p>Something that a profiling tool like SQL Profiler just can&#8217;t do.</p><p>For example by running the code below to insert 200 apples and then retrieve them from the database</p><blockquote><p>Note: this code is meant to be written like this to generate alerts</p></blockquote><pre class="brush: csharp; gutter: true; title: ; toolbar: true; notranslate">
[Test]
public void NHibernate_Profiler_Demo()
{
    using (IStatelessSession session = FruitDatabase.SessionFactory.OpenStatelessSession())
    {
        using (ITransaction txn = session.BeginTransaction(IsolationLevel.ReadCommitted))
        {
            for (int i = 0; i &lt; 200; i++)
            {
                var apple = new Fruit() { Name = &quot;Apple&quot; };
                session.Insert(apple);
            }
            txn.Commit();
        }
    }
    using (IStatelessSession session = FruitDatabase.SessionFactory.OpenStatelessSession())
    {
            var results = session.Query&lt;Fruit&gt;().ToList();
    }
}
</pre><p>the NHibernate Profiler gives a warning about the &#8216;large number of individual writes&#8217; and a suggestion about having &#8216;too many database calls per session&#8217;.</p><p><a
href="http://www.arrangeactassert.com/wp-content/uploads/2011/09/write.png"><img
src="http://www.arrangeactassert.com/wp-content/uploads/2011/09/write.png" alt="" title="NHibernate Profiler Write Alert" width="700" height="433" class="aligncenter size-full wp-image-1963" /></a></p><p>As you can see in the screenshot there are links to read more which takes you to a takes you to a page with helpful tips to resolve issue and a link to ignore the alert (not recommended!).</p><p><a
href="http://www.arrangeactassert.com/wp-content/uploads/2011/09/nhinfo.png"><img
src="http://www.arrangeactassert.com/wp-content/uploads/2011/09/nhinfo.png" alt="" title="NHibernate Info" width="700" height="487" class="aligncenter size-full wp-image-1965" /></a></p><p>This isn&#8217;t the only alert that is raised when writing, so you should repeat the cycle of test and fix until no further alerts are raised, the queries/execution plan and/or code have been optimized e.g. changing how/where identifiers are created.</p><h3 class="subheading">NHibernate Profiler alerts about reads</h3><p>In addition to detecting problems when writing data the NHibernate profiler can give you tips when reading data.</p><p>For the example in this post there are alerts for an unbounded result set and an implicit transaction. Again these probably won&#8217;t be the only alerts raised.</p><p><a
href="http://www.arrangeactassert.com/wp-content/uploads/2011/09/read.png"><img
src="http://www.arrangeactassert.com/wp-content/uploads/2011/09/read.png" alt="" title="NHibernate Profiler Read Alert" width="700" height="433" class="aligncenter size-full wp-image-1964" /></a></p><p>Additional features in the NHibernate Profiler include being able to see the result of the query and the execution plan, the ability to compare sessions and a general overview of how an application is interacting with a database.</p><p>Check out this <a
href="http://nhprof.com/ReportExport.html" title="NH Profiler Demo">live HTML Demo</a> to give it a test run.</p><p>There are also versions available for other ORMs like <a
href="http://efprof.com/" title="Entity Framework Profiler">Entity Framework</a>, unfortunately you&#8217;ll have to buy a separate licence for each one.</p><p>So while you could write your own solution to log and analyse interactions between your app and the database, the NHibernate Profiler will save you so much time because it can do the investigative work for you.</p> ]]></content:encoded> <wfw:commentRss>http://www.arrangeactassert.com/why-i-use-the-nhibernate-profiler-for-optimal-orm-performance/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>ORMs don’t kill databases.  Developers do.</title><link>http://www.arrangeactassert.com/orms-dont-kill-databases-developers-do/</link> <comments>http://www.arrangeactassert.com/orms-dont-kill-databases-developers-do/#comments</comments> <pubDate>Tue, 23 Aug 2011 23:01:24 +0000</pubDate> <dc:creator>Jag Reehal</dc:creator> <category><![CDATA[Entity Framework]]></category> <category><![CDATA[NHibernate]]></category><guid
isPermaLink="false">http://www.arrangeactassert.com/?p=1932</guid> <description><![CDATA[Following a recent post I wrote Phillip Haydon made an excellent argument about not using LINQ in ORMs like nHibernate and Entity Framework without consideration to what they are doing. Something I definitely agree with. Just as guns don’t kill people, ORMs don’t kill databases. Developers do. I should have picked up on this because [...]]]></description> <content:encoded><![CDATA[<p>Following a recent post I wrote <a
href="http://www.philliphaydon.com/2011/08/nhibernate-work-around-is-not-really-a-work-around/" rel="nofollow">Phillip Haydon</a> made an excellent argument about not using LINQ in ORMs like nHibernate and Entity Framework without consideration to what they are doing.</p><p>Something I definitely agree with.</p><blockquote><p>Just as guns don’t kill people, ORMs don’t kill databases.  Developers do.</p></blockquote><div
id="image-text"><p>I should have picked up on this because it’s happened to me on a project I was working on.<br
/> <img
width="100" height="100" src="http://www.arrangeactassert.com/wp-content/uploads/2011/08/tombstone.jpg" alt="Death by ORM" title="tombstone" class="alignleft size-full wp-image-1945" style="margin-right:5px"/><br
/> During development everything was performing well.  So well that even the most sceptical developers decided to use ORMs instead of stored procedures.<br
/> </br>The application was responsive and users were happy.<br
/> </br>However in production there has no happy ending.  The application went from running like <a
href="http://onlineslangdictionary.com/meaning-of/like-shit-off-a-shovel">sh!t off a proverbial shovel</a> to just sh!t.</p></div><p>It was a nightmare and the finger pointing began.</p><p>The problem was we assumed (always a bad thing) the queries generated by the ORM would be as good as if we had written them ourselves.</p><p>So when we looked at what was being generated it came as a bit of a shock to see what was going on.</p><p>But while it was easy to use the ORM as a scapegoat the reality was developers were at fault.</p><p>Here&#8217;s a simple example of how even the smallest of changes can make a difference in the SQL ORMs generate.</p><p>In the code below all we want nHibernate to do is select the of the fruit that is NOT also a color.</p><pre class="brush: csharp; gutter: true; title: ; toolbar: true; notranslate">
[Test]
public void Tale_Of_Two_Queries()
{
    var fruitDatabase = new FruitDatabase();
    using (ISession session = fruitDatabase.Session)
    {
        using (ITransaction txn = session.BeginTransaction())
        {

            var apple = new Fruit() { Name = &quot;Apple&quot;, IsAlsoAColor = false};
            var orange = new Fruit() { Name = &quot;Orange&quot;, IsAlsoAColor = true };

            session.Save(apple);
            session.Save(orange);
            txn.Commit();
        }

        var firstQuery = session.Query&lt;Fruit&gt;()
        .Where(f =&gt; !f.IsAlsoAColor)
        .Select(f =&gt; f.Name)
        .ToList();        

        var secondQuery = session.Query&lt;Fruit&gt;()
                .Where(f =&gt; f.IsAlsoAColor == false)
                .Select(f =&gt; f.Name)
                .ToList();
    }
}
</pre><p>For the query that uses !f.IsAlsoAColor the SQL query looks like this</p><pre class="brush: sql; gutter: true; title: ; toolbar: true; notranslate">
select fruit0_.Name as col_0_0_
from   Fruits fruit0_
where  not (fruit0_.IsAlsoAColor = 1)
</pre><p>For the query that uses f.IsAlsoAColor == false the sql generated looks like this</p><pre class="brush: sql; gutter: true; title: ; toolbar: true; notranslate">
select fruit0_.Name as col_0_0_
from   Fruits fruit0_
where  case
         when fruit0_.IsAlsoAColor = 1 then 1
         else 0
       end = case
               when 0 /* @p0 */ = 1 then 1
               else 0
             end
</pre><p>While this is a trivial example it highlights the fact you don&#8217;t know what the generated SQL will be, let alone the execution plan.</p><p>And if your query returns the results you want are you really going to spend time finding out what’s going on ‘under the hood’?</p><h3 class="subheading">How comes nobody talks about this?</h3><p>I can&#8217;t ever recall a presenter warning about this during any ORM talk I&#8217;ve been to.  The focus always on what it can do and how it compares to other ORMs rather than best practices.</p><h3 class="subheading">It&#8217;s not just a .Net problem either</h3><p>After talking to Ruby on Rails developers this is a problem for them too, because Active Record doesn&#8217;t work 100% of the time.  When it goes wrong they have to implement workarounds to execute queries without using active record.</p><h3 class="subheading">So how can I make sure it doesn&#8217;t happen to me?</h3><p>The first thing is to know what issues to look out for.  The <a
href="http://nhprof.com/Learn/Alerts">nHibernate profiler alerts page</a> is an excellent resource for this.</p><p>With this information you can use profiling tools to see what queries your ORM is generating and how your application is performing.</p><p>My last tip is to always use the best data access method for what you’re doing.  It’s easy to become complacent or aim to everything using an ORM, but if it makes more sense to use a stored procedure then that’s what you should do.</p><p>It would be good to hear what your experiences are with issues like this and to share any tips/tools you have used to avoid ORM performance issues.</p><p>In the meantime I’ll leave you with this excellent DBA vs. Developer (Star Wars Style) video</p><p><iframe
width="420" height="345" src="http://www.youtube.com/embed/P0v3ntSxxYs" frameborder="0" allowfullscreen></iframe></p> ]]></content:encoded> <wfw:commentRss>http://www.arrangeactassert.com/orms-dont-kill-databases-developers-do/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>nHibernate LINQ workaround for System.NotSupportedException</title><link>http://www.arrangeactassert.com/nhibernate-linq-workaround-for-system-notsupportedexception/</link> <comments>http://www.arrangeactassert.com/nhibernate-linq-workaround-for-system-notsupportedexception/#comments</comments> <pubDate>Thu, 11 Aug 2011 23:01:38 +0000</pubDate> <dc:creator>Jag Reehal</dc:creator> <category><![CDATA[NHibernate]]></category><guid
isPermaLink="false">http://www.arrangeactassert.com/?p=1911</guid> <description><![CDATA[In this post we&#8217;ll see a workaround for writing a nHibernate LINQ query that does a join using an in-memory collection. Why would you want to do this? Lets say to find out about nutritional information about fruits users clicked the relevant check boxes and press the button to submit the form e.g. Back on [...]]]></description> <content:encoded><![CDATA[<p>In this post we&#8217;ll see a workaround for writing a nHibernate LINQ query that does a join using an in-memory collection.</p><h3 class="subheading">Why would you want to do this?<br
/></h3><p>Lets say to find out about nutritional information about fruits users clicked the relevant check boxes and press the button to submit the form e.g.</p><p><a
href="http://www.arrangeactassert.com/wp-content/uploads/2011/04/mockup.png"><img
src="http://www.arrangeactassert.com/wp-content/uploads/2011/04/mockup.png" alt="" title="choose fruit mockup" width="450" height="400" class="aligncenter size-full wp-image-1929" /></a></p><p>Back on the server we need to get nutritional information for each fruit selected.</p><p>To get this information we could write a nHibernate LINQ query like this</p><pre class="brush: csharp; gutter: true; highlight: [25,26,27,28]; title: ; toolbar: true; notranslate">
[Test]
public void Getting_Fruits_Using_LINQ_Query()
{
    var fruitIds = new List&lt;int&gt;() { 2, 3 };

    var fruitDatabase = new FruitDatabase();
    using (ISession session = fruitDatabase.Session)
    {
        using (ITransaction txn = session.BeginTransaction())
        {
            // Arrange
            var apple = new Fruit() { Id = 1, Name = &quot;Apple&quot;, NutritionalInformation = &quot;An apple a day&quot; };
            var banana = new Fruit() { Id = 2, Name = &quot;Banana&quot;, NutritionalInformation = &quot;Energy Boost&quot; };
            var orange = new Fruit() { Id = 3, Name = &quot;Orange&quot;, NutritionalInformation = &quot;Lots of Vitamin C&quot; };
            var pear = new Fruit() { Id = 3, Name = &quot;Pear&quot;, NutritionalInformation = &quot;It's green&quot; };

            session.Save(apple);
            session.Save(banana);
            session.Save(orange);
            session.Save(pear);
            txn.Commit();
        }

        // Act
        var result = (from f in session.Query&lt;Fruit&gt;()
                        join i in fruitIds
                            on f.Id equals i
                        select f).ToList();

        // Assert
        Assert.IsFalse(result.Exists(f =&gt; f.Name == &quot;Apple&quot;));
        Assert.IsTrue(result.Exists(f =&gt; f.Name == &quot;Banana&quot;));
        Assert.IsTrue(result.Exists(f =&gt; f.Name == &quot;Orange&quot;));
        Assert.IsFalse(result.Exists(f =&gt; f.Name == &quot;Pear&quot;));
    }
}
</pre><p>but doing so gives us the following error</p><blockquote><p>System.NotSupportedException : Specified method is not supported.</p></blockquote><p>However if we wrote the query like this the join works as expected</p><pre class="brush: csharp; gutter: true; highlight: [25,26,27]; title: ; toolbar: true; notranslate">
[Test]
public void Getting_Fruits_Using_LINQ_Query()
{
    var fruitIds = new List&lt;int&gt;() { 2, 3 };

    var fruitDatabase = new FruitDatabase();
    using (ISession session = fruitDatabase.Session)
    {
        using (ITransaction txn = session.BeginTransaction())
        {
            // Arrange
            var apple = new Fruit() { Id = 1, Name = &quot;Apple&quot;, NutritionalInformation = &quot;An apple a day&quot; };
            var banana = new Fruit() { Id = 2, Name = &quot;Banana&quot;, NutritionalInformation = &quot;Energy Boost&quot; };
            var orange = new Fruit() { Id = 3, Name = &quot;Orange&quot;, NutritionalInformation = &quot;Lots of Vitamin C&quot; };
            var pear = new Fruit() { Id = 3, Name = &quot;Pear&quot;, NutritionalInformation = &quot;It's green&quot; };

            session.Save(apple);
            session.Save(banana);
            session.Save(orange);
            session.Save(pear);
            txn.Commit();
        }

        // Act
     var result = session.Query&lt;Fruit&gt;()
                .Where(f =&gt; fruitIds.Contains(f.Id))
                .ToList();

        // Assert
        Assert.IsFalse(result.Exists(f =&gt; f.Name == &quot;Apple&quot;));
        Assert.IsTrue(result.Exists(f =&gt; f.Name == &quot;Banana&quot;));
        Assert.IsTrue(result.Exists(f =&gt; f.Name == &quot;Orange&quot;));
        Assert.IsFalse(result.Exists(f =&gt; f.Name == &quot;Pear&quot;));
    }
}
</pre><p>For which the SQL generated by nHibernate looks like this</p><pre class="brush: sql; title: ; notranslate">
select fruit0_.Id                     		as Id1_,
       fruit0_.Name                   		as Name1_,
       fruit0_.NutritionalInformation 	as Nutritio3_1_
from   Fruits fruit0_
where  fruit0_.Id in (2 /* @p0 */,3 /* @p1 */)
</pre>]]></content:encoded> <wfw:commentRss>http://www.arrangeactassert.com/nhibernate-linq-workaround-for-system-notsupportedexception/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> </channel> </rss>
<!-- Served from: www.arrangeactassert.com @ 2012-02-06 00:16:37 by W3 Total Cache -->
