{"id":4213,"date":"2015-10-29T10:24:36","date_gmt":"2015-10-29T10:24:36","guid":{"rendered":"https:\/\/ushipblogsubd.wpengine.com\/?p=4213"},"modified":"2025-09-03T16:05:33","modified_gmt":"2025-09-03T16:05:33","slug":"nhibernatemare-elm-street","status":"publish","type":"post","link":"https:\/\/ushipblogsubd.wpengine.com\/shipping-code\/nhibernatemare-elm-street\/","title":{"rendered":"An NHibernateMARE on Elm Street"},"content":{"rendered":"<p>We use (and generally like) the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Object-relational_mapping\" target=\"_blank\" rel=\"noopener\">ORM<\/a> <a href=\"http:\/\/nhibernate.info\/\" target=\"_blank\" rel=\"noopener\">NHibernate<\/a> for MS SQL Server data access, but we understand why you might not.\u00a0Ohhhh, the things we have seen! We\u2019d like to share some of our favorite horrors, so that you can avoid them.<\/p>\n<hr \/>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-4208\" src=\"https:\/\/ushipblogsubd.wpengine.com\/wp-content\/uploads\/2015\/10\/ItCameFromIEnumerable-1024x679.png\" alt=\"It Came From IEnumerable\" width=\"610\" height=\"404\" \/><br \/>\nOriginally, our <tt>Repository&lt;TEntity&gt;<\/tt> base class implemented <tt>IEnumerable&lt;TEntity&gt;<\/tt>. This allowed us to do clever things like<\/p>\n<pre>    foreach (var c in CountryRepository) { \/* \u2026 *\/ }\r\n<\/pre>\n<p>This simple iteration was handy, especially for reference tables (e.g., Countries, States\/Provinces, categories of shippable things). This &#8220;feature&#8221; turned out to be a giant, carnivorous bug. Why you ask? Because LINQ is powerful magic.<\/p>\n<p>It first started when instead of <tt>IUserRepository.Get(userId)<\/tt> someone wrote <tt>IUserRepository.First(x =&gt; x.UserId == userId)<\/tt>. Let&#8217;s take a look at the SQL that is generated by these statements.<\/p>\n<pre>    -- IUserRepository.Get(userId)\r\n\r\n    SELECT\r\n        users0_.Id as Id2_0_,\r\n        users0_.Username as Username2_0_,\r\n        -- ...\r\n    FROM\r\n        [Users] users0_ \r\n    WHERE\r\n        users0_.Id=@p0;\r\n<\/pre>\n<p>But notice the missing <tt>WHERE<\/tt> clause in this next case:<\/p>\n<pre>    -- IUserRepository.First(x =&gt; x.UserId == userId)\r\n\r\n    SELECT\r\n        users0_.Id as Id2_0_,\r\n        users0_.Username as Username2_0_,\r\n        -- ...\r\n    FROM\r\n        [Users] users0_\r\n<\/pre>\n<p>What&#8217;s really happening in the latter case is that the code we accidentally wrote is<\/p>\n<pre>    Enumerable.First(session.Query(), u =&gt; u.Id == usersId)\r\n<\/pre>\n<p>instead of what the developer <em>thought<\/em> they were writing:<\/p>\n<pre>    Queryable.First(session.Query(), u =&gt; u.Id == userId)\r\n<\/pre>\n<p>Unless you don\u2019t mind loading your entire User&#8217;s table into memory every time you look someone up (for us this only took 12 GB of RAM), don\u2019t allow your Repositories to implement IEnumerable.<\/p>\n<hr \/>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4207\" src=\"https:\/\/ushipblogsubd.wpengine.com\/wp-content\/uploads\/2015\/10\/LetTheRightOneIn.png\" alt=\"L?t Den R?tte Komma In\" width=\"527\" height=\"755\" \/><br \/>\nWe can\u2019t tell you whether you should use <tt>nvarchar<\/tt> or <tt>varchar<\/tt> in your application, but we can say that the mappings for <tt>varchar<\/tt> suck (hint: start by using <tt>.Map(...).CustomType(\"AnsiString\")<\/tt> to map your <tt>varchar<\/tt> mappings). Regardless of what you choose, you must know exactly what values you\u2019re putting into your database, and equally important, what you\u2019re getting back out.<\/p>\n<p>The problem: this guy <span style=\"font-size: larger\">\u0ca0_\u0ca0<\/span><\/p>\n<p>Or rather, the guy who chose that as his username.<\/p>\n<p>First we mapped an Entity\u2019s string property to a <tt>varchar<\/tt> column (non-Unicode string data) instead of <tt>nvarchar<\/tt> (Unicode string data). However, what we actually store in the database as his username is &#8220;<tt>?_?<\/tt>&#8221; since every high Unicode character is stored as a single question mark.<\/p>\n<p>Second, we included a non-slug-ified, user-defined value (username) in the canonical URI of an API resource. In other words, the username &#8220;JohnDoe&#8221; would be included in the API URI as the path<\/p>\n<pre>    \/users\/johndoe\r\n<\/pre>\n<p>But <em>that<\/em> guy\u2026 his URI is<\/p>\n<pre>    \/users\/?_?\r\n<\/pre>\n<p>Got that? We made this transformation by mistake:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4215\" src=\"https:\/\/ushipblogsubd.wpengine.com\/wp-content\/uploads\/2015\/10\/disapprovingface.png\" alt=\"disapprovingface\" width=\"348\" height=\"87\" \/><\/p>\n<p style=\"text-align: center;font-size: smaller;margin-top: 0.2em\">we turned his disapproving face into tears<\/p>\n<p>For anyone who knows <a href=\"https:\/\/tools.ietf.org\/html\/rfc3986\" target=\"_blank\" rel=\"noopener\">RFC-3986<\/a>, you will understand why this doesn\u2019t work. &#8216;<tt>?<\/tt>&#8216; separates the path from the query in a URI. Sadly it took us a few users who were unable to retrieve their profiles before we figured this one out.<\/p>\n<p>Here&#8217;s the lesson: Know what you\u2019re storing in your database. If you choose to store non-Unicode string data, prohibit arbitrary Unicode characters in data entry and user input validation. Otherwise, this is how we feel about you: \u0ca0_\u0ca0<\/p>\n<hr \/>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4210\" src=\"https:\/\/ushipblogsubd.wpengine.com\/wp-content\/uploads\/2015\/10\/NightOfTheLivingConnections.png\" alt=\"Night Of The Living Connections\" width=\"846\" height=\"636\" \/><\/p>\n<p>You can\u2019t have a Halloween blog without <a href=\"https:\/\/www.youtube.com\/watch?v=VzpHspD6tNo\" target=\"_blank\" rel=\"noopener\">zombies<\/a>, right?<\/p>\n<p>Suppose you&#8217;re programming along, minding your own business, using your oh-so-convenient Session-per-Request pattern, when you come upon a stack trace containing <tt>CheckNotZombied()<\/tt>. In our case, this is another issue that arose from the intersection of a couple different problems.<\/p>\n<p>At first we came across a blog stating this can be caused by one of two problems:<\/p>\n<ul>\n<li>The database was throwing exceptions with a severity of 20 or<br \/>\nhigher<\/li>\n<li>A transaction is shared by multiple threads<\/li>\n<\/ul>\n<p>We initially hoped the problem was caused by the former since it would involve just following the stack trace. Naturally, it ended up being the latter.<\/p>\n<p>It turns out that years ago, we wrote some slow code in a non-critical, uncommon code path (mobile push notifications). But the database query it ran really was too slow, so after receiving numerous timeout exceptions, we <span style=\"text-decoration: line-through\">rewrote it to be more performant<\/span> swallowed all exceptions and ran it on another thread.<\/p>\n<p>It took about 3 years for the problem to arise, but then, every once in awhile, a random zombie exception would creep up in random places. When we finally traced the calls, we found that they were coming from inside this code!<\/p>\n<pre class=\"\">    ISession session = mySessionFactory.OpenSession();\r\n    new Thread(() =&gt; {\r\n        try {\r\n            \/\/ Intensive queries with session here...\r\n        } catch (Exception) {\r\n            if (session.Transaction != null\r\n                &amp;&amp; session.Transaction.IsOpen()) {\r\n                try {\r\n                    session.Transaction.Rollback();\r\n                } catch (Exception) {\r\n                    \/\/ Q: What's the worst that could happen?\r\n                    \/\/ A: It\u2019s pretty bad.\r\n                }\r\n            }\r\n        }\r\n    }).Start();\r\n<\/pre>\n<p>The non-critical, uncommon code path had became more popular over three years. Turns out the whole \u201csmart phone\u201d ended up being more than a fad. Luckily we were able to fix the problem fairly easily since <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=com.unwirednation.notifications.android.ushipnew\" target=\"_blank\" rel=\"noopener\">uShip&#8217;s native mobile app<\/a> necessiated a rewrite of push notifications using <a href=\"https:\/\/aws.amazon.com\/sns\/\" target=\"_blank\" rel=\"noopener\">Amazon SNS<\/a>.<\/p>\n<p>Here are a couple of guidelines to help you avoid such a terrible fate:<\/p>\n<ol>\n<li>Trace, profile, and log &#8217;til it hurts<\/li>\n<li>Don\u2019t share NHibernate Sessions between threads<\/li>\n<li>When you want to accomplish work concurrently, and the work is IO-bound, prefer <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/hh191443.aspx\" target=\"_blank\" rel=\"noopener\">async methods<\/a> to threads<\/li>\n<li>And don\u2019t forget, just like zombies, sometimes all your ORM needs is <a href=\"https:\/\/youtu.be\/YCVMuevcCvY\" target=\"_blank\" rel=\"noopener\">a little love<\/a><\/li>\n<\/ol>\n<hr \/>\n<h2>Conclusion<\/h2>\n<p>NHibernate&#8217;s pluses have definitely outweighed the minuses for us, but it&#8217;s not without it&#8217;s hidden horrors. Are you able to relate? Share your NHibernate scary stories in the comments! And Happy NHalloween!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We use (and generally like) the ORM NHibernate for MS SQL Server data access, but we understand why you might not.\u00a0Ohhhh, the things we have seen! We\u2019d like to share some of our favorite horrors, so that you can avoid them. Originally, our Repository&lt;TEntity&gt; base class implemented IEnumerable&lt;TEntity&gt;. This allowed us to do clever things&#8230;<a class=\"read-more\" href=\"https:\/\/ushipblogsubd.wpengine.com\/shipping-code\/nhibernatemare-elm-street\/\"> Read More<\/a><\/p>\n","protected":false},"author":15,"featured_media":4209,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[295,2],"tags":[25,36,37,297],"class_list":["post-4213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-shipping-code","category-company-news","tag-api","tag-i18n","tag-nhibernate","tag-shipping-code"],"acf":{"blog_post_content":null},"_links":{"self":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts\/4213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/comments?post=4213"}],"version-history":[{"count":0,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/posts\/4213\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/media\/4209"}],"wp:attachment":[{"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/media?parent=4213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/categories?post=4213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ushipblogsubd.wpengine.com\/wp-json\/wp\/v2\/tags?post=4213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}