Jason Dentler.com
2022-11-07T10:32:49+00:00
http://jasondentler.com
Jason Dentler
jasondentler@gmail.com
NHibernate and TransactionScope and Web API
2015-04-19T03:00:00+00:00
http://jasondentler.com/blog/2015/04/nhibernate-and-transactionscope-and-web-api
<p>###The problem
I have a Web API project that uses NHibernate and NServiceBus, and I need them to succeed or fail together, within a business transaction. There is exactly one transaction per web request.</p>
<p>###What I tried
To enlist in and coordinate the distributed transaction, I need to wrap each web request in a <code class="language-plaintext highlighter-rouge">TransactionScope</code>. I set up an <code class="language-plaintext highlighter-rouge">ActionFilter</code>.</p>
<p>Inside the transaction scope, I need to set up the standard NHibernate session-per-request unit of work. I set up another <code class="language-plaintext highlighter-rouge">ActionFilter</code>.</p>
<p>#####Action Filter order
<a href="http://stackoverflow.com/questions/21628467/order-of-execution-with-multiple-filters-in-web-api">Action filters don’t get executed in a specific order.</a> I couldn’t ensure the transaction scope would be opened before the NHibernate session. A slightly modified version of <a href="http://stackoverflow.com/questions/21628467/order-of-execution-with-multiple-filters-in-web-api">this</a> ordered filter provider worked.</p>
<p>#####Per request
I’m using <a href="http://structuremap.github.io/the-container/nested-containers/">StructureMap nested containers</a> to ensure everything gets cleaned up at the end of each request, even if the filter gets jacked up. This matches up really well with the Web API concept of <a href="http://www.asp.net/web-api/overview/advanced/dependency-injection">dependency scopes / dependency resolver</a>.</p>
<p>#####Lazy loading
I’m using NHibernate lazy loading and LINQ deferred execution in a few responses. I don’t have to do it that way, but it was already written, and I’d rather just make it work. The issue is that when the response is serialized, the LINQ query is executed, which triggers lazy loading. <a href="http://www.asp.net/media/4071077/aspnet-web-api-poster.pdf">By the time this happens</a>, my filter’s <code class="language-plaintext highlighter-rouge">OnActionExecuted</code> has already run. The NHibernate session is already closed.</p>
<p>The solution was to use a message handler instead of filters.</p>
<p>###The (partial) solution
<script src="https://gist.github.com/jasondentler/b9ea3d83586102eb9a67.js?file=UnitOfWorkHandler.cs">
</script></p>
<p>I pass in the factory delegates to make the handler testable.</p>
<p>#####Can’t detect ambient transaction
The standard way to detect an ambient transaction didn’t work for me. <code class="language-plaintext highlighter-rouge">Transaction.Current</code> was always <code class="language-plaintext highlighter-rouge">null</code>. I suspect an issue flowing it across async / await. For now, every request gets a transaction, whether it needs it or not.
<script src="https://gist.github.com/jasondentler/b9ea3d83586102eb9a67.js?file=ambient%20transaction.cs"></script></p>
<p>#####Still lazy loading issues
So far, this works flawlessly when the controller actions return something other than <code class="language-plaintext highlighter-rouge">void</code>, <code class="language-plaintext highlighter-rouge">HttpResponseMessage</code> or an <code class="language-plaintext highlighter-rouge">IHttpActionResult</code>. Check out the Result Conversions box in the lower right corner of the <a href="http://www.asp.net/media/4071077/aspnet-web-api-poster.pdf">ASP.NET Web API 2 lifecycle poster</a> to understand why.</p>
<p>If I need more control over the responses, I have to return either <code class="language-plaintext highlighter-rouge">HttpResponseMessage</code> or <code class="language-plaintext highlighter-rouge">IHttpActionResult</code>. Now the service can return more intelligent responses like custom 404 messages, descriptive 409 conflict responses, 302 redirects, etc. The drawback is that these responses aren’t serialized at the same point in the request lifecycle. In fact, they aren’t serialized inside the Web API stack at all. It’s left up to the host.</p>
<p>This means my lazy loading issue continues. To fix it once and for all, I need to serialize the response content before the NHibernate session gets closed. The simplest solution I could come up with required a second message handler.
<script src="https://gist.github.com/jasondentler/b9ea3d83586102eb9a67.js?file=SerializationHandler.cs"></script></p>
<p>#####Wiring it up
Here’s how to wire up these two new message handlers.
<script src="https://gist.github.com/jasondentler/b9ea3d83586102eb9a67.js?file=Global.asax.cs"></script></p>
NServiceBus and SignalR
2012-02-26T20:34:49+00:00
http://jasondentler.com/blog/2012/02/nservicebus-and-signalr
<p>###The Inspiration
<a href="https://twitter.com/#!/darioquintana">Dario Quintana</a> shared <a href="http://www.asp.net/single-page-application/an-introduction-to-spa/overview/landingpage">this</a> on Twitter. The Single Page Application is something new in ASP.NET MVC 4. As near as I can tell, it’s an HTML and javascript front-end tied to an Entity Framework back end. I haven’t looked at the code, so I’ll withhold judgement.</p>
<p>I started thinking about how I could build a responsive, postback-free user experience in an application with a rich business layer or even a <a href="http://www.udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere%E2%80%A6/">collaborative domain</a> without drowning in AJAX.</p>
<p>###NServiceBus messaging architecture
I ripped off this architecture from smart people™ like Udi Dahan and Greg Young. I have no doubt they would say I’m doing it completely wrong.</p>
<p>Let’s say we have a single bounded context / service / autonomous bounded context / whatever, and it uses a standard command and event system to communicate between the UI and the domain - something like this:
<img src="/images/commands-and-events.png" alt="Commands and Events Diagram" /></p>
<p>Of course, NServiceBus lets us send commands reliably from the web application to the domain, and then publish the resulting events from the domain to any subscribed event handlers.</p>
<p>###SignalR
SignalR hubs are magical. This is the first framework I’ve seen that lets us seamlessly call browser javascript methods from the server.</p>
<p>In the server:
<script src="https://gist.github.com/1911998.js?file=SignalRServerToClient.cs">
</script></p>
<p>In the browser:</p>
<script src="https://gist.github.com/1911998.js?file=SignalRServerToClient.js">
</script>
<p>This updates the stats on every browser with a connection to that hub.</p>
<p>If that weren’t enough, we can also call methods on the server, written in C#, from javascript running in the browser. All of the plumbing is handled for you.</p>
<p>In the browser:
<script src="https://gist.github.com/1911998.js?file=SignalRClientToServer.js">
</script></p>
<p>In the server:
<script src="https://gist.github.com/1911998.js?file=SignalRClientToServer.cs">
</script>
###A growling web application
It’s not hard to imagine a rich browser application where the web server is mostly serving static files and SignalR hub connections.</p>
<p>Let’s say we want to take our messaging architecture and wire it up to build a Growl-type notification system. We can add an extra set of event handlers, this time inside our web application, to push those events through SignalR hubs down to the browsers, where they pop up notifications for events each user cares about.</p>
<p>Here’s an example: You’re visiting an auction website. You’ve placed a bid on an item. As you browse the site for other items, wouldn’t it be nice to know when you’ve been outbid?</p>
<p>The server-side might look something like this:
<script src="https://gist.github.com/1911998.js?file=AuctionHub.cs">
</script></p>
<p>SignalR lets us put clients in to groups. When a customer bids on an item, we add them to the group for that item. We use <code class="language-plaintext highlighter-rouge">Clients[message.ItemId]</code> to reference the group of clients interested in this particular item. We tell all of their browsers to call the <code class="language-plaintext highlighter-rouge">auctionHub.onBidAccepted</code> method, and pass the item id, the item name, and the new highest bid.</p>
<p>Using Pines Notify, the client-side code might look something like this:
<script src="https://gist.github.com/1911998.js?file=AuctionGrowl.js">
</script></p>
<p>###Imagine the possibilities
This is just a quick and dirty example. What if you pushed events down to a javascript MVVM framework like KnockoutJS to keep pages updated in real time? Building real, responsive thick-client apps in a browser isn’t difficult.</p>
Continuous Integration: Rake, Albacore, TeamCity, Kiln, and NuGet
2012-02-18T13:22:14+00:00
http://jasondentler.com/blog/2012/02/continuous-integration-rake
<p>Let’s talk about Continuous Integration.</p>
<p>We started building a system at work. It’s actually several UIs over a common domain and infrastructure, and includes refactoring and integrating a lot of legacy apps. We’ve split it up in to different solutions: Core & Infrastructure, Domain, Legacy, and UI.</p>
<p>###Rake & Albacore
Rake and albacore are an absolute joy to use. All the other .NET build tools I’ve tried ignore this one small fact: programmers code. Yes, it’s Ruby. No, I won’t be followig this up with a passive-agressive, dolphin-filled <a href="http://twitter.com/dhh">@DHH</a> bromance post simultaneously denouncing and praising the .NET community.</p>
<p>You should absolutely give this a try today. I mean Rake, not the “.NET sucks. I’m leaving” post.</p>
<p>###TeamCity
Those JetBrans guys are pretty smart. TeamCity just gets it right. It’s easy to set up. We’re using a nightly build of TeamCity 7 so we can easily host the nuget packages we build. TeamCity checks out the code from Kiln, runs rake to update dependencies (nuget packages from our other solutions) and build the solution, then runs our tests and packages up our nugets.</p>
<p>We have a minor issue where the TeamCity nuget feed sometimes has multiple versions of a package marked IsLatestVersion. This may be fixed already, but we haven’t updated to a newer build. No one else has reported the issue.</p>
<p>###Kiln & Mercurial
IMO, Kiln is the GitHub of Mercurial (for commercial use, at least). The tight integration with FogBugz is nice.</p>
<p>I like mercurial. I don’t like mercurial as much as git. I believe the “git sucks on windows” argument is FUD. I haven’t found a proper branching strategy I like on Mercurial, but I haven’t spent much time looking either. Mercurial is noticably slower than git for getting a status and pushing commits.</p>
<p>###NuGet
In our continuous integration family, this is the ginger kid who ate one too many lead paint chips at grandma’s house. I completly blew two sprints trying to hack around nuget issues.</p>
<p>The story goes like this:</p>
<ol>
<li>Some dim bulb at apache decided that <a href="http://logging.apache.org/log4net/release/faq.html#two-snks">log4net 1.2.11 needed to use different keys</a> for their assembly signing so anyone can patch it and sign it with the official key.</li>
<li><a href="http://nuget.org/profiles/cincura.net">Another dim bulb</a>, perhaps at Apache, perhaps not, decided to publish <a href="http://nuget.org/packages/log4net">a log4net 1.2.11 package</a> using the new key.</li>
<li>Even though it’s compatible with log4net 1.2.11, the NServiceBus 3.0 package had to be locked down to log4net 1.2.10 only to <a href="http://tech.groups.yahoo.com/group/nservicebus/message/12489">work around the signing issues</a>.</li>
</ol>
<p>We have other packages that rely on log4net and don’t have this restriction.</p>
<p>When a project updated to log4net 1.2.11, even accidentally, nuget pack used it as the minimum compatible version.</p>
<p>When that happened, we couldn’t use NServiceBus and our package in the same project anymore, and we’d have to go fix the log4net version mess in the other solution, rebuild, and republish. This was almost never as simple as uninstalling the wrong version and reinstalling the right version.</p>
<p>NuGet allows you to use different versions of a package for different projects in the same solution. This is horribly, terribly, inexcusably wrong. One version per solution should be the default behavior, but it’s not even an option. I don’t know what the hell <a href="http://twitter.com/haacked">@haacked</a> is thinking.</p>
<p>We kept spilling version soup all over our solutions - a stain that doesn’t wash out easily.</p>
<p>I tried to work around this by using the -excludeVersions command line argument, but that wasn’t available from the UI or powershell and broke more than it fixed.</p>
<p>Finally, we gave up. We set up a second non-TeamCity nuget server (actually, just a file share with .nupkg files) to host exactly one version of each external package we use. I don’t like this. It has the same bitter taste as nanny-state firewall rules.</p>
<p>A few good things came out of all this:</p>
<ul>
<li>My build script is capital-a Awesome™</li>
<li>I have disturbingly intimate knowledge of csproj files and their relation to packages.config.</li>
<li>I can hack together a rake script in seconds with Ruby only a mother could love.</li>
</ul>
New and improved Simple.Data.RawSql package released
2012-01-21T10:30:00+00:00
http://jasondentler.com/blog/2012/01/new-and-improved-simple-dot-data-dot-rawsql-package-released
<p>Today, I published my first nuget package, <a href="https://github.com/jasondentler/Simple.Data.RawSql">Simple.Data.RawSql</a>, a set of extensions to <a href="https://github.com/markrendle/Simple.Data">Simple.Data</a> for raw sql queries. It includes some syntax improvements over the code from my <a href="http://jasondentler.com/blog/2012/01/sql-to-simple-dot-data/">previous post</a>.</p>
<p>Here’s a few examples. First up, querying a single row:</p>
<script src="https://gist.github.com/1653230.js?file=singlerow.cs">
</script>
<p>Notice that we specify the type for the <code class="language-plaintext highlighter-rouge">db</code> variable. <code class="language-plaintext highlighter-rouge">Database.Open</code> returns <code class="language-plaintext highlighter-rouge">dynamic</code>. If we left it as <code class="language-plaintext highlighter-rouge">dynamic</code> (or used <code class="language-plaintext highlighter-rouge">var</code>), we couldn’t call our <code class="language-plaintext highlighter-rouge">ToRow</code> extension method.</p>
<p>To query several rows:</p>
<script src="https://gist.github.com/1653230.js?file=rows.cs">
</script>
<p>Finally, you may want to batch several queries together and return multiple result sets:</p>
<script src="https://gist.github.com/1653230.js?file=resultsets.cs">
</script>
SQL to Simple.Data
2012-01-16T19:44:00+00:00
http://jasondentler.com/blog/2012/01/sql-to-simple-dot-data
<blockquote>
<p>Update: <a href="/blog/2012/01/new-and-improved-simple-dot-data-dot-rawsql-package-released/">Published to nuget as Simple.Data.RawSql with syntax improvements.</a></p>
</blockquote>
<p>I like Simple.Data, but I waste a lot of time translating from the SQL in my head to Simple.Data, particularly when my queries get a little weird. No more! Mark Rendle gave me a tip to bypass the query side of Simple.Data while still using the part I really like: the dynamic results.</p>
<p>Each query can return 3 possible results:</p>
<ul>
<li>Multiple result sets</li>
<li>Multiple rows</li>
<li>A single row</li>
</ul>
<p>Of course, if you just want a scalar value, use command.ExecuteScalar().</p>
<p>Here’s the trick. Simple.Data.Ado includes extension methods on data readers to convert the data in to dictionaries, and SimpleRecord (the “dynamic” that represents a row in Simple.Data) has a constructor that accepts a dictionary.</p>
<p>####Using it</p>
<p>Let’s say you want to query a page and count of Albums and Artists from the Chinook database. It might look something like this:</p>
<script src="https://gist.github.com/1626280.js?file=Program.cs">
</script>
<p>####Read from a data reader</p>
<script src="https://gist.github.com/1626280.js?file=DataReaderExtensions.cs">
</script>
<p>####The rest</p>
<p>Grab the rest of the code from <a href="https://gist.github.com/1626280">this gist</a></p>
Hiring a Houston Senior Developer
2012-01-02T00:00:00+00:00
http://jasondentler.com/blog/2012/01/hiring-a-houston-senior-developer
<p>We’re hiring another Senior .NET Developer to add to our team of six. Here’s a few things you should know about us:</p>
<ul>
<li>
<p><em>We enjoy working.</em></p>
<p>We have fun at work. We geek out a lot.</p>
</li>
<li>
<p><em>We enjoy learning.</em></p>
<p>We read books and blogs. We try out new ideas. We share what we learn.</p>
</li>
<li>
<p><em>We question “best practices.”</em></p>
<p>We use Mercurial, not TFS. We use NHibernate, not EF. We’re not afraid of open source. We use what works best.</p>
</li>
</ul>
<p>Here’s a few things we want to know about you:</p>
<ul>
<li>
<p><em>Can you code?</em></p>
<p>In addition to hammering out some C#, SQL, and a little JavaScript, you can navigate Visual Studio with ease. Not only do you understand recursion and simple set algebra, but you know when and how to use them in your code.</p>
</li>
<li>
<p><em>Are you a good fit?</em></p>
<p>We want to know what makes you unique and interesting. You should fit well with the team.</p>
</li>
</ul>
<p><a href="http://davidweekleyhomes.com">David Weekley Homes</a> is located at <a href="http://maps.google.com/maps?daddr=1111+N+Post+Oak+Rd,+Houston,+TX+77024">1111 N Post Oak Road</a>, near 610 and I-10. Our benefits include a huge discount on a new home and profit sharing.</p>
<p>We’re also hiring two more Junior Developers this summer.</p>
New Year, New Blog Engine
2012-01-01T00:00:00+00:00
http://jasondentler.com/blog/2012/01/new-year-new-blog-engine
<p><a href="https://github.com/mojombo/jekyll">Jekyll</a> rocks. Seriously. It renders markdown and liquid templates down to static html files. What’s not to like?</p>
<p>GoDaddy sucks. Seriously. The elephant hunting, SOPA supporting, public relations disaster of a company finally lost my business.</p>
<p>We all know <a href="http://github.com">GitHub</a> rocks. Seriously. Now they get to host my blog. <a href="http://github.com/jasondentler/jasondentler.github.com">Here’s the source</a>, including my awesome rake file. ;)</p>
<p>I transferred my domain to <a href="http://namecheap.com">Namecheap</a>. They’ve raised $64k to help the <a href="https://www.eff.org/">EFF</a> fight <a href="http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act#Arguments_against">SOPA</a>.</p>
<p>Finally, Two Tone Cadillac by T-Bird and the Breaks rocks. Seriously. <a href="http://amzn.com/B001R36GO8">Give it a listen.</a></p>
NHibernate Read Models: An Elephant in the Elevator
2011-12-03T00:00:00+00:00
http://jasondentler.com/blog/2011/12/nhibernate-read-models-an-elephant-in-the-elevator
<p>Our company website is a mostly well-architected <a href="http://nhforge.org/">NHibernate</a> web application. There’s a few data access related performance problems, like ghost writes. I’m confident these issues account for most of the slowness, but the site is still pretty snappy considering we just set debug=”false” and hit publish. </p> <p>Entities were modeled after the business and mapped on to a proper 3rd normal form database with no aggregate boundaries. The object graph for a given query can easily be 5 or 6 layers deep. Translated in to SQL, this means an explosion of joins. The vast majority of the database is populated nightly from SSIS packages and otherwise completely read-only.</p> <p>I’ve seen this movie before. Hell, I’ve directed, starred in, and won an Oscar for this movie. Haven’t we all? The database is modeled after the business, and then pinched and pulled and squished to service a query-heavy application or query-only web site. By the time you’ve finally pushed that NHibernate elephant in to the elevator, you and your app are bruised and brittle.</p> <p>We did all that work to get to a point where we’re murdering our SQL database with the same joins over and over. It would require MUCH less processing power to pre-calculate each view model and make it easy to fetch quickly.</p> <p>This past week, I attended the <a href="http://www.headspring.com/services/developer-training/nservicebus-boot-camp" target="_blank">NServiceBus Boot Camp</a>. What an amazing Christmas gift! I can’t recommend it enough. I wish we’d had time to dig in to CQRS read models more, but here’s a few points on the topic:</p> <ol> <li>The read model SQL database lives on the web server. Think of it as a cache, just more explicit. </li> <li>Domain processing happens elsewhere and publishes events. </li> <li>Handlers on the web server handle those events and update the read model accordingly. NHibernate feels heavy here. Consider a Micro-ORM. </li> <li>Reads go directly to the local database. Query with something really light, then bind the result to the page. </li> </ol> <p>Though I haven’t tried it, I suspect <a href="http://ayende.com/blog/136196/when-should-you-use-ravendb" target="_blank">RavenDB would be a good alternative to SQL on the web server</a>.</p>
Review: NHibernate 3 Beginner's Guide
2011-09-28T00:00:00+00:00
http://jasondentler.com/blog/2011/09/review-nhibernate-3-beginners-guide
<p>There’s a new <a href="http://nhforge.org/">NHibernate</a> book on the market: <a href="http://lostechies.com/gabrielschenker/2011/08/29/nhibernate-3-beginners-guide-published/" target="_blank">NHibernate 3 Beginner’s Guide</a> by Gabriel Schenker. Gabriel is the guy behind the now-offline NHibernate FAQ site. For years, it was one of the best sites on the subject.</p> <p>His style is straight forward and simple. It’s a surprisingly quick read, with all the right information to get up to speed on NHibernate quickly. He’s careful not to leave the reader wondering about key terms or jumping ahead to understand concepts. </p> <p>It’s more than just an update to the 2.x version. Gabriel has rewritten this book <strong>from scratch</strong> and avoided all of the issues of the previous book. Most importantly, he takes a <strong>model-first approach</strong>. This is the beginner’s guide I would share with my coworkers, and, in fact, I have. You should absolutely buy this book for your team.</p>
NHibernate 3 Beginner's Guide published
2011-08-30T00:00:00+00:00
http://jasondentler.com/blog/2011/08/nhibernate-3-beginners-guide-published
<p>Gabriel Schener’s new book, <a href="http://lostechies.com/gabrielschenker/2011/08/29/nhibernate-3-beginners-guide-published/" target="_blank">NHibernate 3 Beginner’s Guide</a> was published today. Go check it out. Gabriel knows NHibernate inside and out – certainly better than me – and worked hard to give the community the best book possible. For technical reviewers, he was backed up by two of the best:Fabio Maulo and Jose Romaniello.</p> <p>Disclosure: Gabriel was an amazing technical reviewer on my book, NHibernate 3.0 Cookbook, along with Jose, <a href="http://fabiomaulo.blogspot.com/">Fabio</a>, and Tuna Toksoz. Packt Publishing published both NHibernate 3 Beginner’s Guide and <a href="http://www.packtpub.com/nhibernate-3-0-cookbook/book?utm_source=jasondentler.com&utm_medium=blog&utm_content=authorsite&utm_campaign=mdb_004974">NHibernate 3.0 Cookbook</a>.</p>
Back to Reality
2011-08-18T00:00:00+00:00
http://jasondentler.com/blog/2011/08/back-to-reality
<p><strong>CONTAINS 0% CODE. WARNING: MAY CONTAIN FEELINGS.</strong></p> <p>Ryan Hartzog has been trying to recruit me for the past 8 months. As he put it, he wore me down. At the end of the month, I leave the college to go to work for David Weekley Homes. </p> <p>Here’s a few things that stuck with me:</p> <ol> <li>It’s not “Human Resources” it’s “People.”</li> <li>When I arrived, the receptionist greeted me by name, knew exactly who I was to meet, where I should be, and when I should be there.</li> <li>The interview & assessment process began at 9am and lasted well in to the afternoon. If they go through all this effort for everyone, they must be picky about who they select.</li> <li>The all-day interview process never felt grueling. I lost count of the number of times I was offered a beverage or asked if I needed a break.</li> <li>The team invited me in. We cut up and had a good time. I found a fellow Sci-Fi fan. Someone on the team has an aversion to Asian cuisine, and another to glitter. I was introduced to “Evil Donna,” who, it turns out, is not evil after all.</li> <li>By the end of the day, it was pretty clear these people enjoy their jobs and each other. I didn’t hear a grumble or see a frown all day, even in passing. </li> <li>They pushed through the process as quickly as possible (at my request), always set clear expectations, and were prompt in making an offer.</li> </ol> <p>I’m heading back to “the real world.”</p>
Hermes: Pub/Sub for the web
2011-07-19T00:00:00+00:00
http://jasondentler.com/blog/2011/07/hermes-pubsub-for-the-web
<p><a href="http://farm1.static.flickr.com/108/311690195_00a12b6bac_o.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 4px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="HermesSandal" border="0" alt="HermesSandal" align="left" src="http://jasondentler.com/blog/wp-content/uploads/2011/07/HermesSandal1.jpg" width="240" height="180" /></a></p> <p>Once in a while, some new disruptive technology comes along that unseats the established giants. <a href="https://github.com/TellagoDevLabs/Hermes" target="_blank">Hermes</a> is a new open source Pub/Sub library from <a href="http://www.tellago.com/" target="_blank">Tellago</a> DevLabs. This little REST service could unseat a giant or two.</p> <p>Here are a few reasons you should give it a try.</p> <p><strong>Hermes is standard</strong>. It’s a <a href="http://martinfowler.com/articles/richardsonMaturityModel.html#level3" target="_blank">RMM level 3</a> REST service and speaks standard HTTP and XML. JSON support is planned. </p> <p><strong>Hermes is scalable.</strong> Hermes doesn’t waste resources tracking subscriptions, maintaining connections to transactional message queues, and fighting the web’s nature to push data around the globe. Instead, messages are stored in Mongo DB and published to atom feeds. Clients poll these feeds for new messages. The web is built on polling. In fact…</p> <p><strong>Hermes is web scale</strong>. Obviously, I don’t mean it could host Twitter on your old laptop. Hermes takes advantage of the web to scale. A Squid reverse proxy server will solve any scalability problems most of us could encounter. If subscribers are overwhelming your server, cache the atom feeds for a fraction of a second. If new messages are streaming in too fast, distribute the load across several Hermes servers. Or even better, let <a href="http://www.mongodb.org/display/DOCS/Amazon+EC2" target="_blank">Amazon</a> or <a href="http://www.mongodb.org/display/DOCS/MongoDB+on+Azure" target="_blank">Microsoft</a> worry about it all. This isn’t your father’s enterprise middleware style pub/sub.</p> <p><strong>Hermes is simple.</strong> The REST service really pushes you where you need to go. I’ve got big plans for Hermes in a project at work, so I’ve been working on the Javascript client library. Even with my limited understanding of the language, it was pretty easy. </p> <p><strong>Give it a try.</strong> Hermes uses the BSD license. </p> <p>Here’s a chat example:in 17 lines of Javascript:</p> <p>[gist id=1087550 file=ChatClient.js] </p> <p>Hermes sandal photo © <a href="http://www.flickr.com/photos/ecastro/">ecastro</a> and licensed under <a href="http://creativecommons.org/licenses/by/2.0/">Creative Commons Attribution 2.0</a></p>
Did you mean CarsBucks?
2011-07-05T00:00:00+00:00
http://jasondentler.com/blog/2011/07/did-you-mean-carsbucks
<p><a href="http://www.flickr.com/photos/xfer/4124684/" target="_blank"><img style="margin: 4px 10px; display: inline; float: left" align="left" src="http://farm1.static.flickr.com/4/4124684_2eb7b898b8_z_d.jpg?zz=1" width="240" height="181" /></a>I’ve been working on a little hobby project for ASP.NET MVC / CQRS apps, and I showed it off to my friend <a href="http://joseoncode.com/" target="_blank">Jose</a>. I asked if I could recreate his Chinook Media Manager app with MVC and CQRS as an example for this new project. As usual, he pointed me to something even better: Restbucks, the example from the <a href="http://restinpractice.com/default.aspx" target="_blank">REST in Practice</a> book. </p> <p>Jose has <a href="http://restbuckson.net/" target="_blank">already implemented this</a> example in .NET as a full REST (HATEOAS) service using WCF over a traditional <a href="http://nhforge.org/">NHibernate</a> model.</p> <p>I set off to build it over using CQRS. I started with nCQRS, but they’ve had string of bad pull requests applied recently. After 2 days of hacking at the framework to get a build and all-green tests, I switched to Greg Young’s 100-line SimpleCQRS. From there, it was smooth sailing again.</p> <p>So, I give you the <a href="https://github.com/jasondentler/cqrs#readme" target="_blank">“Did you mean CarsBucks?” example</a>, Restbucks reimagined as a CQRS domain.</p> <p>I may not know exactly what I’m doing, but I’m doing it anyway. Constructive feedback is always welcome. Also, this may deviate from Restbucks slightly. I’m not finished with the book.</p> <p><font size="1">(Coffee cup image licensed under CC BY-SA 2.0 by Marcelo Alves)</font></p>
NHibernate 3.0 released
2010-12-05T00:00:00+00:00
http://jasondentler.com/blog/2010/12/nhibernate-3-0-released
<p>First, <a href="http://www.packtpub.com/nhibernate-3-0-cookbook/book?utm_source=jasondentler.com&utm_medium=blog&utm_content=authorsite&utm_campaign=mdb_004974">NHibernate 3.0 Cookbook</a> is now a Packt Publishing best seller. Thank you everyone who bought a copy. The NHibernate project gets a portion of each and every sale.</p> <p>Yesterday, <a href="http://fabiomaulo.blogspot.com/">Fabio</a> announced the release of <a href="http://nhforge.org/">NHibernate</a> 3.0 General Availability. Go get it! </p> <p>The previous official release of NHibernate was version 2.1.2, just over 1 year ago. Since then, the team has made a ton of improvements and bug fixes.</p> <p>Most importantly, NHibernate now targets .NET 3.5, allowing us to use lambda expressions and LINQ. This has led to an explosion of new ways to configure and query. </p> <p>There are a few very minor breaking changes mentioned in the release notes:</p> <ul> <li><a href="http://216.121.112.228/browse/NH-2392" target="_blank">[NH-2392]</a> ICompositeUserType.NullSafeSet method signature has changed</li> <li><a href="http://216.121.112.228/browse/NH-2199" target="_blank">[NH-2199]</a> null values in maps/dictionaries are no longer silently ignored/deleted</li> <li><a href="http://216.121.112.228/browse/NH-1894" target="_blank">[NH-1894]</a> SybaseAnywhereDialect has been removed, and replaced with SybaseASA9Dialect. Sybase Adaptive Server Enterprise (ASE) dialects removed.</li> <li><a href="http://216.121.112.228/browse/NH-2251" target="_blank">[NH-2251]</a> Signature change for GetLimitString in Dialect</li> <li><a href="http://216.121.112.228/browse/NH-2284" target="_blank">[NH-2284]</a> Obsolete members removed</li> <li><a href="http://216.121.112.228/browse/NH-2358" target="_blank">[NH-2358]</a> DateTimeOffset type now works as a DateTimeOffset instead a "surrogate" of DateTime</li> </ul> <p>Plans for version 3.1 include additional bug fixes and patches, as well as enhancements for the new LINQ provider.</p> <p>As Fabio says, Happy Persisting!</p>
Simple CQRS + NHibernate event store
2010-10-10T00:00:00+00:00
http://jasondentler.com/blog/2010/10/simple-cqrs-nhibernate-event-store
<p>I had hoped to include a CQRS-related recipe in the Data Access Layer chapter of <a href="http://www.packtpub.com/nhibernate-3-0-cookbook/book?utm_source=jasondentler.com&utm_medium=blog&utm_content=authorsite&utm_campaign=mdb_004974" target="_blank">my book</a>. Of course, not having any real world CQRS experience myself, I couldn't offer any authoritative guidance. Now that I have some free time, I'm determined to remedy that situation. </p> <p>I won't go in to the specifics of CQRS or even event sourcing. The internet already has plenty of people explaining it better than I ever could. If you're like me, you need code to learn. You need to hack away at something for a few days before you really get it. </p> <p>In the spirit of "learning in the open," I'm sharing this weekend's effort to fix up <a href="http://github.com/gregoryyoung/m-r" target="_blank">Greg Young's Simple CQRS example</a>. His solution is called "SimplestPossibleThing.sln" which describes it perfectly. It's a great learning tool, but it's all built on top of in-memory collections, not persistent storage. </p> <p>In this post, I'm going to make his event store persistent. With some luck, I'll move on to the read model and bring it full circle in a later post. </p> Before we dive in, take a look at <a href="http://github.com/gregoryyoung/m-r/blob/master/SimpleCQRS/EventStore.cs" target="_blank">Greg's in-memory implementation</a>. There's a few things to note: <ol> <li>Rather than persisting the actual events, he’s “persisting” EventDescriptor structs with references to the Events. I’m going to steal this idea to make our NHibernate code easier. </li> <li>The expectedVersion parameter should match the version of the most recent event. When it doesn’t, we know we have a concurrency violation. </li> </ol> <h4>A persistent event store</h4> <p>First, let's do a little refactoring of the EventStore implementation:</p> <pre class="brush:csharp">public abstract class BaseEventStore : IEventStore
{
private readonly IEventPublisher _publisher;
protected BaseEventStore(IEventPublisher publisher)
{
_publisher = publisher;
}
public void SaveEvents(Guid aggregateId,
IEnumerable<Event> events,
int expectedVersion)
{
var eventDescriptors = new List<EventDescriptor>();
var i = expectedVersion;
foreach (var @event in events)
{
i++;
@event.Version = i;
eventDescriptors.Add(new EventDescriptor(aggregateId, @event, i));
}
AddEvents(eventDescriptors, aggregateId, expectedVersion);
foreach (var @event in events)
{
_publisher.Publish(@event);
}
}
public List<Event> GetEventsForAggregate(Guid aggregateId)
{
var eventDescriptors = GetEventDescriptorsForAggregate(aggregateId);
if (null == eventDescriptors || !eventDescriptors.Any())
{
throw new AggregateNotFoundException();
}
return eventDescriptors.Select(desc => desc.EventData).ToList();
}
protected abstract IEnumerable<EventDescriptor>
LoadEventDescriptorsForAggregate(Guid aggregateId);
protected abstract void PersistEventDescriptors(
IEnumerable<EventDescriptor> newEventDescriptors,
Guid aggregateId,
int expectedVersion);
}</pre>
<h4>Concurrency violation checking</h4>
<p>Greg's implementation explicitly checked for concurrency violations before persisting. Since he's working in memory, it's a simple check and a cheap operation. With a database, it gets more complicated. We could lock and query for the max version, but that's extreme and unnecessary. </p>
<p>We assume that the expectedVersion value is not greater than the actual current version. Since we're not deleting events from the event stream, I think this is a safe assumption. Essentially, while there's a small chance someone may have done something to our aggregate, they'll never undo something from our aggregate. </p>
<p>We can rely on our database for the check. If we insert an event with version 2 after events 0, 1, 2, and 3 are written, we'll get a primary key constraint violation. Since this is the only PK in our database, we know exactly why this happened. We'll convert this to a ConcurrencyException.</p>
<h4>Persistence implementation</h4>
<p>Now we have a base class that handles the transformation and event publishing and lets us implement our own persistence. </p>
<pre class="brush:csharp">public class NHibernateEventStore : BaseEventStore
{
private readonly IStatelessSession _session;
public NHibernateEventStore(
IEventPublisher publisher,
IStatelessSession session)
: base(publisher)
{
_session = session;
}
protected override IEnumerable<EventDescriptor>
LoadEventDescriptorsForAggregate(Guid aggregateId)
{
var query = _session.GetNamedQuery("LoadEventDescriptors")
.SetGuid("aggregateId", aggregateId);
return Transact(() => query.List<EventDescriptor>());
}
protected override void PersistEventDescriptors(
IEnumerable<EventDescriptor> newEventDescriptors,
Guid aggregateId, int expectedVersion)
{
// Don't bother to check expectedVersion. Since we can't delete
// events, we won't skip a version. If we do have a true concurrency
// violation, we'll get a PK violation exception.
// SqlExceptionConverter will change it to a ConcurrencyViolation.
Transact(() =>
{
foreach (var ed in newEventDescriptors)
_session.Insert(ed);
});
}
protected virtual TResult Transact<TResult>(Func<TResult> func)
{
if (!_session.Transaction.IsActive)
{
// Wrap in transaction
TResult result;
using (var tx = _session.BeginTransaction())
{
result = func.Invoke();
tx.Commit();
}
return result;
}
// Don't wrap;
return func.Invoke();
}
protected virtual void Transact(Action action)
{
Transact<bool>(() =>
{
action.Invoke();
return false;
});
}
}</pre>
<p>We’re using stateless sessions because they’re quick and easy. We don’t need a big unit of work implementation, automatic dirty checking, lazy loading, or any of that other stuff we rely on for traditional applications. We’re just stuffing rows in to a table. </p>
<p>For those of you who’ve read <a href="http://www.packtpub.com/nhibernate-3-0-cookbook/book?utm_source=jasondentler.com&utm_medium=blog&utm_content=authorsite&utm_campaign=mdb_004974" target="_blank">my book</a>, the Transact methods are taken right from the first section of my Data Access Layer chapter. They let us manage the <a href="http://nhforge.org" target="_blank">NHibernate</a> transaction when we need to, and handle it for us when we don’t. </p>
<h4>Query and Model</h4>
<p>The LoadEventDescriptors query is dead simple:</p>
<pre class="brush:xml"><?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<query name="LoadEventDescriptors">
<![CDATA[
from EventDescriptor ed
where ed.Id = :aggregateId
order by ed.Version
]]>
</query>
</hibernate-mapping></pre>
<p>Next, we redesign the EventDescriptor for use with NHibernate.</p>
<pre class="brush:csharp">public class EventDescriptor
{
public Event EventData { get; private set; }
public Guid Id { get; private set; }
public int Version { get; private set; }
public EventDescriptor(Guid id, Event eventData, int version)
{
EventData = eventData;
Version = version;
Id = id;
}
private EventDescriptor()
{
}
public override bool Equals(object obj)
{
return Equals(obj as EventDescriptor);
}
public bool Equals(EventDescriptor other)
{
return null == other
? false
: other.Id == Id && other.Version == Version;
}
public override int GetHashCode()
{
return Id.GetHashCode() ^ Version.GetHashCode();
}
}</pre>
<p>We've switched from a struct to a class, converted the readonly fields to properties with private setters, added a private constructor, and implemented Equals and GetHashCode. We did all of this to make NHibernate happy. We won't be doing any lazy loading, so we don't need to make our properties virtual. Because we'll use a composite key (Id and Version), we need to override Equals and GetHashCode. </p>
<p>Here’s our mapping for EventDescriptor:</p>
<pre class="brush:xml"><?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="SimpleCQRS"
namespace="SimpleCQRS.EventStore">
<typedef class="SimpleCQRS.EventStore.NHibernate.JsonType, SimpleCQRS.EventStore.NHibernate"
name="json" />
<class name="EventDescriptor" table="Events"
mutable="false" lazy="false">
<composite-id>
<key-property name="Id" />
<key-property name="Version" />
</composite-id>
<property name="EventData" type="json" >
<column name="Type"/>
<column name="Data"/>
</property>
</class>
</hibernate-mapping></pre>
<p>EventDescriptor is immutable. We’ve disabled lazy loading. Our primary key is a composite of the Id and Version. Our EventData is stored in two columns. The first stores the assembly qualified name of the .NET type. The second column stores the event as json serialized data. We use the JsonType IUserType to handle the serialization and deserialization transparently. Newtonsoft json.Net does all of the heavy lifting.</p>
<pre class="brush:csharp">[Serializable]
public class JsonType : IUserType
{
private static object Deserialize(string data, string type)
{
return Deserialize(data, TypeNameHelper.GetType(type));
}
private static object Deserialize(string data, Type type)
{
return JsonConvert.DeserializeObject(data, type);
}
private static string Serialize(object value)
{
return null == value
? null
: JsonConvert.SerializeObject(value);
}
private static string GetType(object value)
{
return null == value
? null
: TypeNameHelper.GetSimpleTypeName(value);
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
int typeIndex = rs.GetOrdinal(names[0]);
int dataIndex = rs.GetOrdinal(names[1]);
if (rs.IsDBNull(typeIndex) || rs.IsDBNull(dataIndex))
{
return null;
}
var type = (string) rs.GetValue(typeIndex);
var data = (string) rs.GetValue(dataIndex);
return Deserialize(data, type);
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
if (value == null)
{
NHibernateUtil.String.NullSafeSet(cmd, null, index);
NHibernateUtil.String.NullSafeSet(cmd, null, index + 1);
return;
}
var type = GetType(value);
var data = Serialize(value);
NHibernateUtil.String.NullSafeSet(cmd, type, index);
NHibernateUtil.String.NullSafeSet(cmd, data, index + 1);
}
public object DeepCopy(object value)
{
return value == null
? null
: Deserialize(Serialize(value), GetType(value));
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
var parts = cached as string[];
return parts == null
? null
: Deserialize(parts[1], parts[0]);
}
public object Disassemble(object value)
{
return (value == null)
? null
: new string[]
{
GetType(value),
Serialize(value)
};
}
public SqlType[] SqlTypes
{
get
{
return new[]
{
SqlTypeFactory.GetString(10000), // Type
SqlTypeFactory.GetStringClob(10000) // Data
};
}
}
public Type ReturnedType
{
get { return typeof(Event); }
}
public bool IsMutable
{
get { return false; }
}
public new bool Equals(object x, object y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (ReferenceEquals(null, x) || ReferenceEquals(null, y))
{
return false;
}
return x.Equals(y);
}
public int GetHashCode(object x)
{
return (x == null) ? 0 : x.GetHashCode();
}
}</pre>
TypeNameHelper still needs some work. GetSimpleTypeName should strip out the version, public key, processor architecture, and all that goo from the assembly qualified name.
<pre class="brush:csharp">public static class TypeNameHelper
{
public static string GetSimpleTypeName(object obj)
{
return null == obj
? null
: obj.GetType().AssemblyQualifiedName;
}
public static Type GetType(string simpleTypeName)
{
return Type.GetType(simpleTypeName);
}
}</pre>
<p>Finally, we need a bit of NHibernate magic to convert to primary key constraint violations in to ConcurrencyExceptions. I probably could have made this simpler, but it works.</p>
<pre class="brush:csharp">public class SqlExceptionConverter : ISQLExceptionConverter
{
public Exception Convert(AdoExceptionContextInfo exInfo)
{
var dbException = ADOExceptionHelper.ExtractDbException(exInfo.SqlException);
var ns = dbException.GetType().Namespace ?? string.Empty;
if (ns.ToLowerInvariant().StartsWith("system.data.sqlite"))
{
// SQLite exception
switch (dbException.ErrorCode)
{
case -2147467259: // Abort due to constraint violation
throw new ConcurrencyException();
}
}
if (ns.ToLowerInvariant().StartsWith("system.data.sqlclient"))
{
// MS SQL Server
switch (dbException.ErrorCode)
{
case -2146232060:
throw new ConcurrencyException();
}
}
return SQLStateConverter.HandledNonSpecificException(exInfo.SqlException,
exInfo.Message, exInfo.Sql);
}
}</pre>
<p>Fabio has a <a href="http://fabiomaulo.blogspot.com/2009/06/improving-ado-exception-management-in.html" target="_blank">blog post</a> all about NHibernate’s SQLExceptionConverter. To turn this on, just set the sql_exception_converter property in your NHibernate configuration. </p>
<p>While I was working on this, I ran in to <a href="http://216.121.112.228/browse/NH-2020" target="_blank">NH-2020</a>, despite being closed. Basically, batching and the SQL exception converter don’t mix, so turn off batching. I told <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio</a> about it. I’ll do what I can to get it fixed for good in NH 3 GA. </p>
<p>Thanks to Greg Young for all his efforts to teach the world CQRS through <a href="http://cqrsinfo.com" target="_blank">CQRSInfo.com</a>, including his 6 1/2 hour screen cast. Also, thank you Fabio for sharing your json user type with me and answering my questions. </p>
<p><a href="http://code.google.com/p/jasondentler/source/browse/#svn/trunk/SimpleCQRS" target="_blank">Get yer codez here.</a></p>
We're hiring!
2010-10-07T00:00:00+00:00
http://jasondentler.com/blog/2010/10/were-hiring
<p>Alvin Community College is seeking a great .NET developer to add to our team of three. We are quickly bringing applications online to better serve our students over the web. We need a good general programmer with web application development experience and solid user interface design skills. </p> <h2>We are seeking someone with:</h2> <ul> <li>A curious mind, eager to learn and willing to teach </li> <li>Professional experience with HTML, CSS, JavaScript, and .NET</li> <li>An associate degree or equivalent work experience in a related field</li> </ul> <h2>What you can expect:</h2> <p>You can expect a great place to work with a fantastic team, meaningful projects and great on-going opportunities to learn. </p> <p>For us, a typical application is built with C#, ASP.NET MVC 2, NHibernate 3 on SQL Server, AutoMapper, and jQuery. Our applications integrate with a large educational ERP, Datatel Colleague.</p> <p>Our campus provides all of the standard college amenities, including a gym, cafeteria, coffee bar, library, and college store. We offer a number of amazing benefits including full medical and dental insurance, and teacher’s retirement. In addition to paid sick leave and vacation time, we are off for spring break, winter break, a number of regular holidays, and about 14 Fridays during the summer.</p> <p>$50 - 60k, dependent on experience. <p>Applicants must consent to a standard background check. </p> <h2>Where are we?</h2> <p>Alvin Community College is located at 3110 Mustang Road, Alvin, TX 77511, just 30 minutes South of Houston, TX. </p> <p><iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&source=s_q&hl=en&q=Alvin+Community+College,&sll=29.398011,-95.239406&sspn=0.006917,0.009645&ie=UTF8&t=h&radius=0.35&split=1&rq=1&ev=zi&hq=Alvin+Community+College,&hnear=&ll=29.398113,-95.239406&spn=0.006917,0.009645&output=embed"></iframe><br /><small><a href="http://maps.google.com/maps?f=q&source=embed&hl=en&q=Alvin+Community+College,&sll=29.398011,-95.239406&sspn=0.006917,0.009645&ie=UTF8&t=h&radius=0.35&split=1&rq=1&ev=zi&hq=Alvin+Community+College,&hnear=&ll=29.398113,-95.239406&spn=0.006917,0.009645" style="color:#0000FF;text-align:left">View Larger Map</a></small></p> <h2>How to apply:</h2> <p>Visit <a href="https://jobs.alvincollege.edu/applicants/Central?quickFind=50488">https://jobs.alvincollege.edu/applicants/Central?quickFind=50488</a></p>
NHibernate 3.0 Cookbook released
2010-10-04T00:00:00+00:00
http://jasondentler.com/blog/2010/10/nhibernate-3-0-cookbook-released
<p><a href="https://www.packtpub.com/nhibernate-3-0-cookbook/book" target="_blank">My book is out today!</a> The publisher’s website has the full table of contents, as well as a sample chapter. </p> <p><a href="https://www.packtpub.com/nhibernate-3-0-cookbook/book">https://www.packtpub.com/nhibernate-3-0-cookbook/book</a></p>
September NHibernate News
2010-09-27T00:00:00+00:00
http://jasondentler.com/blog/2010/09/september-nhibernate-news
<p>Here’s some recent news highlights:</p> <ul> <li><a href="http://nhforge.org" target="_blank">NHibernate</a> 3.0 Alpha 3 is out. As the release approaches, expect a new build every couple of weeks.</li> <li>Roger Kratz has joined the NH Contrib team and is helping Simon with Envers. </li> <li><a href="https://www.packtpub.com/nhibernate-3-0-cookbook/book" target="_blank">My book</a> will be shipping very soon, perhaps as soon as next week. Packt Publishing will release the table of contents and sample chapter on their website very soon.</li> <li><a href="http://nhday.eu" target="_blank">NHDay</a> is less than two weeks away. </li> <li>Fabio’s most recent estimate for the release of NHibernate 3.0 GA is around December 9th. </li> </ul>
Pre-order NHibernate 3.0 Cookbook Today!
2010-09-05T00:00:00+00:00
http://jasondentler.com/blog/2010/09/pre-order-nhibernate-3-0-cookbook-today
<p><a href="https://www.packtpub.com/nhibernate-3-0-cookbook/book"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="NHibernate 3.0 Cookbook" border="0" alt="NHibernate 3.0 Cookbook" align="right" src="http://jasondentler.com/blog/wp-content/uploads/2010/09/NH3CookbookCover.png" width="199" height="244" /></a> <a href="https://www.packtpub.com/nhibernate-3-0-cookbook/book">NHibernate 3.0 Cookbook is available for pre-order today!</a> We are working hard to have the book out in time for <a href="http://nhday.eu" target="_blank">NHibernate Day</a> on October 8th.</p> <p>Thank you to the awesome team at Packt Publishing and my <strong>amazing</strong> technical reviewers, <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio Maulo,</a> <a href="http://jfromaniello.blogspot.com/" target="_blank">Jose Romaniello</a>, <a href="http://devlicio.us/blogs/tuna_toksoz" target="_blank">Tuna Toksoz,</a> and <a href="http://www.lostechies.com/blogs/gabrielschenker/default.aspx" target="_blank">Gabriel Schenker</a>, for all the support and guidance. We made a great book! </p> <h5>Overview of NHibernate 3.0 Cookbook</h5> <ul></ul> <ul> <li>Master the full range of NHibernate features </li> <li>Reduce hours of application development time and get better application architecture and performance </li> <li>Create, maintain, and update your database structure automatically with the help of NHibernate </li> <li>Written and tested for NHibernate 3.0 with input from the development team distilled in to easily accessible concepts and examples </li> <li>Part of Packt's Cookbook series: each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible </li> </ul> <p>The NHibernate Cookbook explains each feature of NHibernate 3.0 in detail through example recipes that you can quickly apply to your applications. Set yourself free from stored procedures and inline SQL. Quite simply, if you build .NET applications that use databases, this book is for you.</p> <p>The book will take you from the absolute basics of NHibernate through its most advanced features and beyond, showing you how to take full advantage of each concept to quickly create amazing database applications. Beginners will learn several techniques for each of the 4 core NHibernate tasks – mapping, configuration, session & transaction management, and querying – and which techniques fit best with various types of applications. In short, you will be able to build an application using NHibernate. Intermediate level readers will learn how to best implement enterprise application architecture patterns using NHibernate, leading to clean, easy-to-understand code, and increased productivity. In addition to new v3.0 features, advanced readers will learn creative ways to extend NHibernate core, as well as techniques using the NHibernate search, shards, spatial, and validation projects.</p> <p>Get solutions to common NHibernate problems to develop high-quality performance-critical data access applications</p> <h5><b>What you will learn from this book :</b></h5> <ul></ul> <ul> <li>Create a persistent object model for moving data in and out of your database </li> <li>Build the database from your model automatically </li> <li>Configure NHibernate for use with WebForms, MVC, WPF, and WinForms applications </li> <li>Create database queries using a variety of methods, including the new LINQ to NHibernate and QueryOver APIs </li> <li>Build an enterprise-level data access layer </li> <li>Improve the performance of your applications using a variety of techniques </li> <li>Build an infrastructure for fast, easy test-driven development of your data access layer </li> <li>Extend NHibernate to add data encryption and auditing </li> <li>Implement entity validation, full-text search, horizontal partitioning (sharding), and spatial queries using NHibernate Contrib projects </li> </ul> <h5><b>Approach</b></h5> <p>This book contains quick-paced self-explanatory recipes organized in progressive skill levels and functional areas. Each recipe contains step-by-step instructions about everything necessary to execute a particular task. The book is designed so that you can read it from start to end or just open up any chapter and start following the recipes. In short this book is meant to be the ultimate "how-to" reference for NHibernate 3.0, covering every major feature of NHibernate for all experience levels.</p> <h5><b>Who this book is written for</b></h5> <p>This book is written for NHibernate users at all levels of experience. Examples are written in C# and XML. Some basic knowledge of SQL is assumed.</p>
I'm on Hanselminutes talking about NH 3
2010-07-30T00:00:00+00:00
http://jasondentler.com/blog/2010/07/im-on-hanselminutes-talking-about-nh-3
<p>Our friend <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio</a> was up to no good earlier this week, and as a result, I ended up on <a href="http://www.hanselminutes.com" target="_blank">Hanselminutes</a> talking about NHibernate 3 with <a href="http://www.hanselman.com/blog/" target="_blank">Scott Hanselman</a>. </p> <p>We talk about where to get <a href="http://nhforge.org" target="_blank">NHibernate</a>, a quick overview of starting an NH app, the state of NHForge, tooling and commercial support, the NHibernate ecosystem, and we compare the new EF “unicorn” features to features in NHibernate.</p> <p>So, <a href="http://hanselminutes.com/default.aspx?showID=243" target="_blank">go listen now</a>. </p> <p>Thank you Scott, Fabio, and the guys at Pwop! I think the show turned out great, despite my nerves.</p>
NHibernate 3.0 Alpha 1 released.
2010-07-24T00:00:00+00:00
http://jasondentler.com/blog/2010/07/nhibernate-3-0-alpha-1-released
<p>This morning, <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio</a> released the <a href="http://sourceforge.net/projects/nhibernate/files/" target="_blank">official NH 3 Alpha 1 binaries and source</a> on SourceForge. Go play! </p> <p> </p> <p>Oh, yeah. Frist!!!!!1!!!!one!!</p>
Visual Studio 2010 publish / web.config conflict
2010-07-20T00:00:00+00:00
http://jasondentler.com/blog/2010/07/visual-studio-2010-publish-web-config-conflict
<p>Yesterday, I suddenly and mysteriously started getting this error message when trying to build my ASP.NET MVC 2 application. </p> <blockquote> <p>It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level</p> </blockquote> <p>It’s mysterious because I didn’t change my .configs. Double-clicking on the error took me to the <authentication> section of the web.config at the root of my app. It’s legal to define it there. Strange.</p> <p>After trying a few different things, I started commenting out larger and larger chunks of my config, until it looked like this:</p> <pre class="brush:xml"><configuration><!-- ... --></configuration></pre>
<p>Clearly, the error message was wrong.</p>
<p>As it turns out, this was my first time to build the app after using VS 2010’s Publish feature to throw it up on a server for a demo & user testing. Publishing packages up the website under .objReleasePackage, and it doesn’t clean up after itself. The next time I built my application, the compiler barked because I had a web.config hidden a few layers deep under .obj with an <authentication> element. </p>
<p>I discovered the issue when I compiled my app at the command line and saw the full path on the error message. So, kill the .obj folder after each publish, and you’ll never have this trouble.</p>
NHibernate Auditing v3 - Poor Man's Envers
2010-07-04T00:00:00+00:00
http://jasondentler.com/blog/2010/07/nhibernate-auditing-v3-poor-mans-envers
<p>First, let me explain the title of this post. The Hibernate folks – you know, that <a href="http://nhforge.org" target="_blank">NHibernate</a> knock off written in the Java (pronounced “ex em el”) programming language – have a project called Envers. Among other things, It audits changes to entities, then allows you to easily retrieve the entity as it was at any previous point in time. </p> <p>Well, Simon Duduica is porting this over to .NET and NHibernate, and he’s making some AMAZING progress. On June 28th, he shared this news with us on the NH Contrib development group:</p> <blockquote> <p>Hi everybody,</p> <p>I have news regarding Envers.NET. I've commited a version that works in basic tests for CUD operations, with entities that have relationships between them, also with entities that are not audited. To make things work I had to make two small modifications of NHibernate, both modifications were tested running all NHibernate unit tests and they all passed. I already sent the first modification to Fabio and the second I will send this evening. I would like to thank Tuna for helping me out with good advices when I was stuck :)</p> </blockquote> <p> </p> <p>So, on to the topic of this post. For <u>NHibernate 3.0 Cookbook</u>, I’ve included a section that explains how to use NHibernate to generate audit triggers. Originally, I had planned to use the code from <a href="http://jasondentler.com/blog/2009/12/generate-audit-triggers-from-nhibernate-v2/" target="_blank">my previous blog post on the topic</a>, but I didn’t like its structure. I also didn’t want to include all that plumbing code in the printed book. Instead, I’ve rewritten and contributed the “framework” code to <a href="http://code.google.com/p/unhaddins/" target="_blank">uNHAddIns</a>. The “how-to use it” is explained in the book, so I won’t explain it here.</p> <p>Today, I was writing an integration test for this contribution, and thought the idea was worth sharing. I have a simple Cat class:</p> <p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ClassDiagram1" border="0" alt="ClassDiagram1" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram1.png" width="163" height="143" /> </p> <p>When I do anything to this cat, in addition to the normal INSERT, UPDATE, or DELETE, a database trigger records that action in a table called CatAudit:</p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2010/07/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/image_thumb.png" width="206" height="159" /></a> </p> <p>I wanted an easy way to investigate the contents of this table to prove that my audit triggers worked. Here’s what I came up with, along with help from Jose Romaniello (@jfroma). First, I created a class to match this table:</p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram11.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ClassDiagram1" border="0" alt="ClassDiagram1" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram1_thumb.png" width="150" height="240" /></a> </p> <p>Next, I mapped it, made it readonly and excluded it from hbm2ddl with this mapping:</p> <pre class="brush:xml"><?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="uNhAddIns.Test"
namespace="uNhAddIns.Test.Audit.TriggerGenerator">
<typedef class="NHibernate.Type.EnumStringType`1[[uNhAddIns.Audit.TriggerGenerator.TriggerActions, uNhAddIns]], NHibernate"
name="triggerActions" />
<class name="CatAudit"
mutable="false"
schema-action="none">
<composite-id>
<key-property name="Id" />
<key-property name="AuditUser" />
<key-property name="AuditTimestamp" />
</composite-id>
<property name="Color"/>
<property name="AuditOperation" type="triggerActions" />
</class>
</hibernate-mapping></pre>
<p>I made it readonly by setting mutable="false" and excluded it from hbm2ddl with schema-action="none". That’s it!</p>
<p>By the way, the <typedef> along with type="triggerActions" just tells NHibernate I've stored my TriggerActions enum values as strings, not numbers.</p>
Reviewed: NHibernate 2 Beginner's Guide
2010-06-11T00:00:00+00:00
http://jasondentler.com/blog/2010/06/review-nhibernate-2-beginners-guide
<p><a href="http://jasondentler.com/blog/wp-content/uploads/2010/06/8907OS_MockupCover_Beginersguide2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="8907OS_MockupCover_Beginers guide(2)" border="0" alt="8907OS_MockupCover_Beginers guide(2)" align="left" src="http://jasondentler.com/blog/wp-content/uploads/2010/06/8907OS_MockupCover_Beginersguide2_thumb.jpg" width="198" height="244" /></a> </p> <p><a href="https://www.packtpub.com/nhibernate-2-x-beginners-guide/book" target="_blank">NHibernate 2 Beginner’s Guide</a> by Aaron Cure is the 3rd published <a href="http://nhforge.org/content/Books.aspx" target="_blank">book about NHibernate</a>. Each example in this book is presented in both C# and VB.NET, and some knowledge of these languages, as well as some basic understanding of ASP.NET WebForms is assumed. </p> <p>Overall, for OR/M beginners and Entity Framework refugees, it provides a good foundation of NHibernate knowledge. The examples are simple enough to understand, and can easily be applied to real-world scenarios. There are, however, a few points of concern, such as the database-first approach, and the prescription of code generation.</p> <p>Here’s a quick summary of what’s covered in each chapter:</p> <p>As you might expect, chapter 1 gives a general overview of <a href="http://nhforge.org" target="_blank">NHibernate</a>, along with some code listings. </p> <p>Chapter 2 sets up the database and table structure for the example model. </p> <p>In chapter 3, the author takes us in to the world of POCO model design. He shows us NHibernate data types and their corresponding .NET data types, as well as setting up a collection for a one-to-many relationship. </p> <p>In chapter 4, we begin the mapping process. After just a few pages, we have a completed NHibernate xml mapping. The chapter ends with a nice, quick example of a Fluent NHibernate code mapping. <a href="https://www.packtpub.com/sites/default/files/8907-chapter-4-data-cartography.pdf" target="_blank">Chapter 4 is available for preview on the Packt Website</a>.</p> <p>In chapter 5, we start to get in to true NHibernate territory. The author shows us how to build a session factory, open a session, and then explains the proper use of transactions (Yes!). I would have preferred an example of session-per-request over the session provider singleton. Folks, save a kitten. Don’t use singletons. </p> <p>Chapter 6 shows off all the log4net goodness baked in to NHibernate. </p> <p>Chapter 7 explains the ins and outs of NHibernate configuration, with code and xml examples. </p> <p>Chapter 8 shows us an example Data Access Object and how to build some Criteria queries with projections, paging, and sorting, It’s good stuff for beginners, but it doesn’t cover HQL. </p> <p>In Chapter 9, the author shows us how to use NHibernate with ASP.NET WebForms data binding. No beginner’s book would be complete without showing the Microsoft way. </p> <p>Chapter 10 deals with ASP.NET security and authorization, including a membership provider based on NHibernate.</p> <p>Chapter 11 shows off several code generation tools. While this is the logical destination for anyone using a database-first approach, with a model-first approach, its unnecessary for all but the largest projects. </p> <p><em>Disclosure: In exchange for </em><a href="http://www.packtpub.com/article/author_reviewing_for_packt" target="_blank"><em>non-monetary compensation</em></a><em>, I worked as one of two technical reviewers on this book, and I am currently writing </em><em><u>NHibernate</u></em><em><u> 3 Cookbook</u>, to be published by Packt later this year. </em></p>
March Updates
2010-03-18T00:00:00+00:00
http://jasondentler.com/blog/2010/03/march-updates
<h5>Some news from the month of March. </h5> <p>Simon Duduica of Bucharest, Romania and his team are porting Hibernate Envers to .NET / <a href="http://nhforge.org" target="_blank">NHibernate</a>. </p> <p>Michele Minorello is working on NHibernate Search to add Loquacious configuration and Linq2Lucene. </p> <p>I have a book deal with Packt Publishing. <u>NHibernate 3.0 Cookbook</u> will cover existing and new 3.0 features of NHibernate, as a series of short, easy to follow recipes that can be combined to build great NHibernate applications. In addition to NHibernate 3, the book also covers NHContrib projects, some ideas from uNHAddIns, fluent & auto-mapping with Fluent NHibernate, and ConfORM.</p>
<p>I'd like to send a HUGE thank you to my technical reviewers, including Fabio Maulo, Jose Romaniello, and Tuna Toksoz.</p>
Big hairy bugs and other weird looking stuff.
2010-02-17T00:00:00+00:00
http://jasondentler.com/blog/2010/02/big-hairy-bugs-and-other-weird-looking-stuff
<p>Yesterday, I spent an embarrassing amount of time searching for a bug. I’m sure this is well-documented somewhere on MSDN. It even generates a compiler warning in some cases. Still, it’s not the behavior one would expect from C#.</p> <p>When creating lambdas (including LINQ expressions) inside a for each loop, don’t use the iterator variable in your lambda. Let me explain with some code:</p> <pre class="brush:csharp">foreach (Type controllerType in controllerTypes)
{
kernel.Bind(controllerType).ToSelf().InRequestScope();
kernel.Bind<IController>().ToMethod(ctx => ctx.kernel.Get(controllerType)).Named(GetName(controllerType));
}</pre>
<p>Why am I using a method to get the controller? It just so happens that my AccountController is also a <a href="http://jasondentler.com/blog/2009/11/simple-domain-events/" target="_blank">domain event handler</a> for my AccountNameAlreadyUsed event. This goes back to Ayende's tip in my <a href="http://jasondentler.com/blog/2009/11/simple-domain-events/" target="_blank">domain events post</a>: To get a message back to the UI, fire a new event and have the UI listen for it. In this case, I need the UI to complain when the account name they selected is already being used. </p>
<p>In case your mind has wandered to the dark side, throwing exceptions is not an acceptable way of passing messages in an application.</p>
<p>Now, why the odd mappings? Let's say I bind IController and IHandle<AccountNameAlreadyUsed> to AccountController in the request scope. It doesn't quite work like you would first expect. You will have one instance of AccountController returned for IController and a separate instance for IHandle<AccountNameAlreadyUsed>. </p>
<p>Instead, I’m saying that for each request for an IController, go get an AccountController, essentially delegating the request to the ToSelf() binding. I have a similar ToMethod() lambda binding for IHandle<AccountNameAlreadyUsed>. Since both interface bindings are fulfilled by the ToSelf binding, only one instance of AccountController is created for the request, instead of two.</p>
<p>So, this explains why I need the lambda in the first place. Why didn’t the code above work?</p>
<p>As it turns out, there was some funny business going on underneath the covers between the foreach iterator and the lambda. Here’s the symptom: No matter which “instance” of the lambda was being referenced, inside the lambda, the iterator variable (controllerType) was always the first value that was iterated. No matter which controller I requested, I always got an instance of AccountController, since it happens to be first alphabetically.</p>
<p>Once you realize what’s going on, the fix is simple. Create another variable and use it inside the lambda instead. So, instead of the code above, we get this:</p>
<pre class="brush:csharp">foreach (Type controllerType in controllerTypes)
{
var controllerType2 = controllerType;
kernel.Bind(controllerType).ToSelf().InRequestScope();
kernel.Bind<IController>().ToMethod(ctx => ctx.kernel.Get(controllerType2)).Named(GetName(controllerType));
}</pre>
<p>If, instead of a lambda, we had a LINQ expression, the compiler would generate a warning about this issue – at least in VB.NET. If I hadn’t already seen that warning from LINQ expressions, I would probably still be bug hunting.</p>
<p>Jason</p>
February Updates
2010-02-04T00:00:00+00:00
http://jasondentler.com/blog/2010/02/february-updates
<p>I have a few quick announcements.</p> <ul> <li><a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio</a> has been busy on some really amazing <a href="http://fabiomaulo.blogspot.com/2010/01/map-nhibernate-using-your-api.html" target="_blank">mapping</a> <a href="http://fabiomaulo.blogspot.com/2010/02/conform-nhibernate-un-mapping.html" target="_blank">magic</a>.</li> <li>Aaron Cure’s <a href="http://www.packtpub.com/nhibernate-2-x-beginners-guide/book" target="_blank">NHibernate 2.x Beginners Guide</a> from Packt Publishing will be out in May.</li> <li>I’m making progress on Project <a href="http://code.google.com/p/nenverse/" target="_blank">Nenverse</a>. The concept is similar to Hibernate’s Envers. I’m not ready to announce it to the world just yet, but you want to look over the code or even contribute, it’s out there.</li> <li>In an effort to avoid meta-blogging at all cost, I won’t mention the cool new stuff over on the right, or the new text up above.</li> </ul> <p>That’s it for now.</p>
Sharpening My C# Skills
2010-01-12T00:00:00+00:00
http://jasondentler.com/blog/2010/01/sharpening-my-c-skills
<p>You may have noticed a lack of VB.NET source code on my blog recently. There’s a reason. I’ve always been able to read and write C#. at least enough to order off the menu or ask for directions to the Men’s room. </p> <p>The ALT.NET crowd is almost exclusively C#, except where they’ve moved beyond it.  If I’m going to participate, it’s past time for me to become fluent. Until at least April, I won’t write a single line of VB.NET outside of work. </p>
Exploiting Context_Info for Fun and Audit
2010-01-02T00:00:00+00:00
http://jasondentler.com/blog/2010/01/exploiting-context_info-for-fun-and-audit
<p>This is a continuation of my posts about auditing with triggers. </p> <h3>The Problem</h3> <p>My previous examples have used system_user as the source of user information in the audit log, which required you to impersonate users down to the database level, that is to open the connection in the context of the application user, not some shared generic account. There are several reasons why this is not a good idea:</p> <ol> <li>You either don’t have per-user credentials appropriate to create SQL server accounts (typical in public-facing web applications), or are unable to do so for various reasons ranging from security concerns to account management workload. </li> <li>When each user authenticates with their own credentials, this effectively disables connection pooling. Especially in high-volume web scenarios, this will kill performance and put a strain on server resources. </li> <li>I believe the loss of connection pooling will also burn through your license pool with per-user licensed SQL servers. I may be mistaken on this point, as I haven’t worked with a per-user licensed SQL server for the better part of a decade. </li> <li>If you are unwilling to use SQL server authentication, you will most likely have to set up Kerberos constrained delegation so that your database server trusts your web server to authenticate users. This is a royal PITA to implement. </li> </ol> <h3>The Trouble With Triggers</h3> <p>As far as input inside a trigger, you only have access to the data being manipulated, system functions, and very little else. You can’t use SELECT statements in triggers either, at least not against normal tables and views. </p> <h3>SQL Context Info</h3> <p>Starting with MS SQL Server 2000, you can associate up to 128 bytes of data with the current connection using the SET CONTEXT_INFO command. Starting with SQL 2005, you can use the CONTEXT_INFO function to retrieve this data. This data is available everywhere, including triggers. </p> <p>If you use connection pooling (and you probably are), this data is not reset when the connection is reused. </p> <p>To set your context info data, use the <a href="http://msdn.microsoft.com/en-us/library/aa259199(SQL.80).aspx" target="_blank">SET CONTEXT_INFO</a> command like so:</p> <pre class="brush:sql">DECLARE @Ctx varbinary(128)
SELECT @Ctx = CONVERT(varbinary(128), 'My context data goes here.')
SET CONTEXT_INFO @Ctx</pre>
<p>SET CONTEXT_INFO can only be used with variables and constants, meaning you can’t CONVERT data types or concatenate strings or any other calculation in the same command. </p>
<p>To retrieve the context data, use the <a href="http://msdn.microsoft.com/en-us/library/ms180125(SQL.90).aspx" target="_blank">CONTEXT_INFO</a> function:</p>
<pre class="brush:sql">DECLARE @CtxData varchar(128)
SELECT @CtxData = CONVERT(VarChar(128), CONTEXT_INFO())
PRINT @CtxData</pre>
<p>This will output ‘My context data goes here.’ etc. Note – The is ASCII character 0 (NULL). Why? We’re converting the string to fixed-length binary and then converting it back.</p>
<h3>Know Your Roots</h3>
<p><a href="http://jasondentler.com/blog/wp-content/uploads/2010/01/image.png"><img style="border-right-width: 0px; margin: 4px 10px 4px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://jasondentler.com/blog/wp-content/uploads/2010/01/image_thumb.png" width="137" height="59" /></a> There was a time when programmers weren’t protected from the fact that strings are just chunks of memory. Just like programmers in the old days, you have two options: Pascal strings or C strings. You can stuff a length byte at the beginning of your context as in Pascal, or you can search for the null termination of your string as in the C language. </p>
<p>Also, because nchar and nvarchar are UNICODE UCS-2 strings, they use two bytes (of your 128 maximum) per character. char and varchar only use one byte per character, but the character set is limited. It’s a trade-off. </p>
<h3>How does this help me?</h3>
<p>We can use context info data to get information from our application in to our audit triggers. For example, we can get the current user name from our application or evem some identifying information about the location in our application, such as the name of the controller and action that triggered the event. Just be conscious of the 128 byte limitation. It's probably better to store an id for more information such as the id of the user account, or an id that references some lookup table with application locations.</p>
<h3>The Code, Sir. </h3>
<p>We will override the GetConntion() method of DriverConnectionProvider so that every NHibernate connection will have the current username stored in the context.</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Connection;
using System.Data;
namespace NHibernate.Connection
{
public class ContextDriverConnectionProvider : DriverConnectionProvider
{
public override System.Data.IDbConnection GetConnection()
{
var conn = base.GetConnection();
SetContext(conn);
return conn;
}
private const string CONTEXT_SQL = "declare @Length tinyintndeclare @Ctx varbinary(128)nselect @Length = len(@username)nselect @Ctx = convert(binary(1), @Length) + convert(varbinary(127), @username)nset context_info @Ctx";
protected virtual void SetContext(IDbConnection conn)
{
IDbCommand cmd = conn.CreateCommand();
IDbDataParameter param = cmd.CreateParameter();
cmd.CommandType = CommandType.Text;
cmd.CommandText = CONTEXT_SQL;
param.ParameterName = "@username";
param.DbType = DbType.AnsiString;
param.Size = 127;
param.Value = System.Environmnt.UserName;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
}
}
}</pre>
<p>This will run the following SQL code when NHibernate opens a SQL connection. Note that @username is a variable defined as a parameter on our IDbCommand. Also, I chose to use Pascal strings with the length stored in the first byte.</p>
<pre class="brush:sql">declare @Length tinyint
declare @Ctx varbinary(128)
select @Length = len(@username)
select @Ctx = convert(binary(1), @Length) + convert(varbinary(127), @username)
set context_info @Ctx</pre>
<p>We'll alter our trigger code to get the username from the context instead of system_user.</p>
<pre class="brush:sql">set nocount on
declare @Username varchar(127)
declare @Length tinyint
declare @Ctx varbinary(128)
select @Ctx = CONTEXT_INFO()
select @Length = convert(tinyint, substring(@Ctx, 1, 1))
select @Username = convert(varchar(127), substring(@Ctx, 2, 1 + @Length))
if (@Username is null) select @Username = SYSTEM_USER</pre>
<h3>Security Implications</h3>
<p>I am not a security expert. I am certainly not a SQL security expert. However, I believe this method is secure for most scenarios. In my opinion, this is at least as secure as auditing through NHibernate interceptors and events. </p>
<p>Here’s a few ways to circumvent the system, and how you can prevent that from happening:</p>
<ul>
<li><strong>Manipulate the audit logs directly.</strong> Obviously, in any audit scenario, you should set permission on your audit tables to make them select and insert only. </li>
<li><strong>Alter the context_info data directly.</strong> A user overwrites their own context_info with that of another user, effectively blaming their actions on someone else. This can be done through a SQL injection attack some other security breach. If you go on vacation with the front door open, don’t be surprised when your house is robbed. </li>
<li><strong>Fail to set context_info.</strong> Again, this requires some other security breach. You may also change your trigger code to ROLLBACK TRANSACTION and RAISERROR when context_info is not set. This will force a rollback of the transaction (or in the case of no explicit transaction, the SQL statement that caused the trigger), abort the remainder of the SQL batch, and report an error. The approach requires everyone, including your DBA, to set an appropriate context_info before altering any audited data. </li>
</ul>
<p>This is certainly my worst blog post this year, but don’t worry. I can do worse. </p>
<p>- Jason</p>
Generate Audit Triggers from NHibernate v2
2009-12-31T00:00:00+00:00
http://jasondentler.com/blog/2009/12/generate-audit-triggers-from-nhibernate-v2
<p>In my <a href="http://jasondentler.com/blog/2009/12/generate-audit-triggers-from-nhibernate/" target="_blank">December 23rd post</a>, I showed you how to generate audit tables and triggers from your <a href="http://nhforge.org" target="_blank">NHibernate</a> mappings. Since then, I had an amazing conversation with <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio Maulo</a>, NHibernate project owner, where among other things, he showed me a much better way to accomplish the same task.</p> <p>In my last post, we used the NHibernate mapping as source data to create our script by hand. With this version, we’re going to take it a step further. When you add an IAuxilaryDatabaseObject to the mappings, it will be included in the ddl output of SchemaExport. These have no effect outside of SchemaExport. It’s a simple way to include additional items in your database setup scripts.</p> <p>In our main program, we set up some additional columns to hold our audit data – user, timestamp, and action. These columns will be added to each audit table. Then, we use TriggerStrategy to add auxiliary database objects to our configuration.</p> <pre class="brush:csharp"> static void AddAuditing(Configuration cfg)
{
var columns = new List<auditcolumn>();
columns.Add(new AuditColumn() {
Name = "AuditUser",
SqlType = "sysname",
IsNullable = false,
ValueFunction = delegate(TriggerActions actions)
{
return "system_user";
}
});
columns.Add(new AuditColumn()
{
Name = "AuditTimestamp",
Value = new SimpleValue() { TypeName = NHibernate.NHibernateUtil.DateTime.Name },
IsNullable = false,
IncludeInPrimaryKey = true,
ValueFunction = delegate(TriggerActions actions)
{
return "getdate()";
}
});
columns.Add(new AuditColumn()
{
Name = "AuditOperation",
Value = new SimpleValue() { TypeName = NHibernate.NHibernateUtil.AnsiChar.Name },
Length = 1,
IsNullable = false,
ValueFunction = delegate(TriggerActions actions)
{
switch (actions)
{
case TriggerActions.Insert:
return "'I'";
case TriggerActions.Update:
return "'U'";
case TriggerActions.Delete:
return "'D'";
default:
throw new ApplicationException("Triggers handling multiple event types (INSERT, UPDATE, DELETE) are unsupported. ");
}
}
});
new NHibernate.Audit.TriggerStrategy(
new NHibernate.Audit.AuditTableBuilder(),
new NHibernate.Audit.MsSqlTriggerBuilder(),
columns).Configure(cfg);
}</pre>
<p>Trigger strategy simply hands off the work of audit table builder and trigger builder.</p>
<p>Audit table builder creates an audit table object for each table already in your mapping. It is also responsible for calculating the name of each audit table. Yes, the naming should probably be pulled in to a separate class, but oh well.</p>
<p>Audit table uses NHibernate's table object internally to create a duplicate of each table, plus the additional audit columns, then exposes the drop/create scripts for this table object as an IAuxilaryDatabaseObject. I've ommitted some of the name-related static below.</p>
<pre class="brush:csharp">using System.Collections.Generic;
using NHibernate.Mapping;
namespace NHibernate.Mapping
{
public class AuditTable : AbstractAuxiliaryDatabaseObject
{
public AuditTable(string Name, Table DataTable, IEnumerable<AuditColumn> AuditColumns)
{
dataTable = DataTable;
auditTable = new Table();
auditColumns = AuditColumns;
BuildAuditTable(Name);
}
protected readonly Table dataTable;
protected readonly Table auditTable;
protected readonly IEnumerable<AuditColumn> auditColumns;
protected virtual void BuildAuditTable(string Name)
{
auditTable.Catalog = dataTable.Catalog;
auditTable.Schema = dataTable.GetQuotedSchema();
auditTable.Name = Name;
foreach (Column column in dataTable.ColumnIterator)
CopyColumn(column);
CopyPrimaryKey(dataTable);
AddAuditColumns();
}
protected virtual void CopyColumn(Column column)
{
auditTable.AddColumn((Column)column.Clone());
}
protected virtual void CopyPrimaryKey(Table dataTable)
{
if (dataTable.PrimaryKey != null)
{
var pk = new PrimaryKey();
auditTable.PrimaryKey = pk;
foreach (Column c in dataTable.PrimaryKey.ColumnIterator)
{
Column auditTableColumn = auditTable.ColumnIterator.WithName(c.Name);
pk.AddColumn(auditTableColumn);
}
}
else
{
throw new System.NotSupportedException("Tables without primary keys are not supported.");
}
}
protected virtual void AddAuditColumns()
{
foreach (AuditColumn source in auditColumns)
{
Column dest = (Column)source.Clone();
auditTable.AddColumn(dest);
if (source.IncludeInPrimaryKey)
auditTable.PrimaryKey.AddColumn(dest);
}
}
public override string SqlCreateString(NHibernate.Dialect.Dialect dialect, NHibernate.Engine.IMapping p, string defaultCatalog, string defaultSchema)
{
return auditTable.SqlCreateString(dialect, p, defaultCatalog, defaultSchema);
}
public override string SqlDropString(NHibernate.Dialect.Dialect dialect, string defaultCatalog, string defaultSchema)
{
return auditTable.SqlDropString(dialect, defaultCatalog, defaultSchema);
}
}
}</pre>
<p>That handles our audit tables. Now let’s look at the triggers.</p>
<p>Abstract trigger builder builds insert, update, and delete triggers for each table. You should override BuildTriggerBody to customize the body of your trigger. I’ve created MsSqlTriggerBuilder to output my preferred trigger code. </p>
<p>NHibernate dialects have no concept of triggers and lack the required strings to build a DBMS-specific CREATE TRIGGER statements. Instead, you specify a trigger type inherited from AbstractTrigger specific to your database to build the CREATE TRIGGER statement. I’ve included MsSqlTrigger.</p>
<p> </p>
<p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/12/Triggers1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="Triggers" border="0" alt="Triggers" src="http://jasondentler.com/blog/wp-content/uploads/2009/12/Triggers_thumb1.png" width="578" height="821" /></a></p>
<p> </p>
<p>That’s all folks. You can grab the code from my SVN repository at <a href="http://basiclyeverything.googlecode.com/svn/trunk/AuditLogExample/">http://basiclyeverything.googlecode.com/svn/trunk/AuditLogExample/</a></p>
<p>Since I’m still using the system_user function to get the current user, you will still need to impersonate the user all the way down to the database level. I’ve found a way around this, and I will show it to you next time. Until then, Happy New Year.</p>
Generate Audit Triggers From NHibernate
2009-12-23T00:00:00+00:00
http://jasondentler.com/blog/2009/12/generate-audit-triggers-from-nhibernate
<p>Last week, <a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio</a> was showing me the <a href="http://martinfowler.com/eaaDev/ParallelModel.html" target="_blank">Parallel Models</a> pattern and explaining some of the work he’s doing with it. It is a VERY powerful concept.</p> <p>What I’m going to show you today is the poor-mans version. It certainly doesn’t qualify as parallel model, but it’s pretty good audit logging if you meet the prerequisites.</p> <h4>The Problem</h4> <p>You need some audit logs for your current application, but you’re behind. In fact, you started the project already a month behind schedule. This needs to be quick and reliable. It’d be great if it didn’t intrude on the application, because you’ve got enough rattling around in your head already.</p> <p>It sounds like you want SQL trigger audit logging. By the way, let’s say you’re using MS SQL Server. Let’s also say your application impersonates the user all the way down to the database level. That means your connection string says integrated security=SSPI or your dba enjoys the extra work of maintaining a sql login for each user. Those are prerequisites for this approach.</p> <h4>What’s a trigger?</h4> <blockquote> <p>A trigger is a special kind of stored procedure that automatically executes when an event occurs in the database server. <br />- <a href="http://msdn.microsoft.com/en-us/library/ms189799.aspx" target="_blank">CREATE TRIGGER, MSDN</a></p> </blockquote> <p>If tables are the data structures in your database and stored procedures are the methods, then triggers are the event handlers. We’re concerned with three specific events – INSERT, UPDATE, and DELETE. We want to log each time those events happen to rows in our tables.</p> <p>Trigger auditing has been around since at least the 1990s – since before SQL Server was even worth a damn. That’s MSSQL 6.5 folks. It’s sturdy and well-proven, although poorly implemented triggers will bring your server to a screeching halt. Fair warning – mine may be one of them.</p> <p>We want to know what the data was before the change, what the data is now, who changed it, and when.</p> <p>When you insert records in a table, the insert trigger for that table executes. The same goes for update and delete.</p> <p>Triggers have two imaginary tables to help us with this task – inserted and deleted. Inside a trigger, <a href="http://msdn.microsoft.com/en-us/library/ms191300.aspx" target="_blank">they mostly work like real tables</a>. Inserted always has the new data. Deleted always has the old data (from before the change.) So, in the case of an INSERT trigger, deleted is empty. For a DELETE trigger, inserted is always empty, since there is no new data with a deletion. For an UPDATE trigger, they both have data.</p> <p>How does this help us? Well, suppose we have want to audit a table called Person. Let’s make a table called Audit_Person with the exact same columns as Person. When we delete data from Person, our DELETE trigger on Person will run. Inside our trigger, the deleted table has all of the rows that were just deleted from Person. We can copy that data to our audit table so we have a record of it by doing INSERT INTO Audit_Person SELECT * FROM deleted. Since the columns match up exactly, it works.</p> <p>Wait a minute though. We need to know who deleted that data and when. Oh, and we need some way to indicate the different events.</p> <p>Lucky for us, there’s some easy functions in SQL. system_user will give us the login of the current user – either a sql account name or a windows account name. Of course, GetDate() will tell us the current time and we’ll just write that to the table.</p> <p>Let’s go ahead and write out a full trigger.</p> <pre class="brush:sql">CREATE TRIGGER Person_onInsert ON Person FOR INSERT AS
SET NOCOUNT ON
INSERT INTO Audit_Person SELECT *, system_user, getdate(), 'I' FROM Inserted</pre>
<p>Oh yeah, we need to add some fields in Audit_Person to hold the extra stuff. system_user is a custom sql type called sysname. It’s really nvarchar(256). Of course, getdate() is a datetime. Finally, we’re passing a capital letter I (for Inserted) as the last field, so we’ll need to make that a char(1) type. </p>
<p>The SET NOCOUNT ON command is there to suppress the extra (X rows affected) messages that SQL spits out. You’ll know what I’m talking about if you’ve ever clicked on the Messages tab after running a query. </p>
<p>So, that’s the audit logging. Now we just need to create an audit table and 3 triggers for each table in your application.</p>
<h4>What does that get us?</h4>
<p>Suppose we set up the audit table and all 3 triggers, then ran these 5 SQL commands:</p>
<pre class="brush:sql">INSERT INTO [Person] VALUES (NEWID(), 'Jason 1')
INSERT INTO [Person] VALUES (NEWID(), 'Jason 2')
INSERT INTO [Person] VALUES (NEWID(), 'Jason 3')
UPDATE Person SET Name = 'Jason 4'
DELETE FROM Person </pre>
<p>Our Audit_Person table would have these rows: (click the picture for 100% size)</p>
<p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/12/image3.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/12/image_thumb3.png" width="554" height="156" /></a></p>
<p> </p>
<h4>Being Lazy</h4>
<p>You’ve got 200 tables? Well, you’d better get to typing then. </p>
<p></p>
<p>OK. Just like you can generate a SQL script using <a href="http://nhforge.org" target="_blank">NHibernate</a>.Tool.hbm2ddl.SchemaExport, we can generate a script to build our audit tables and triggers from the mappings.</p>
<p>Now, we’re not going to parse out the XML in the hbm files. We’re going to read the proposed table schema – what SchemaExport will give you – directly from the NHibernate configuration object. This is the same way SchemaExport does it’s magic.</p>
<p>Here’s the code:</p>
<pre class="brush:csharp">using System.IO;
using NHibernate.Cfg;
using NHibernate.Mapping;
using NHibernate.AdoNet.Util;
namespace AuditLogExample
{
public class AuditScripter
{
public const string USER_DEFAULT = "system_user";
public const string TIMESTAMP_DEFAULT = "getdate()";
private enum Operations
{
Insert,
Update,
Delete
}
public AuditScripter(Configuration Configuration)
{
cfg = Configuration;
mapping = cfg.BuildMapping();
dialect = NHibernate.Dialect.Dialect.GetDialect(cfg.Properties);
formatter = (NHibernate.Util.PropertiesHelper.GetBoolean(NHibernate.Cfg.Environment.FormatSql, cfg.Properties, true) ? FormatStyle.Ddl : FormatStyle.None).Formatter;
}
private readonly NHibernate.Dialect.Dialect dialect;
private readonly Configuration cfg;
private readonly NHibernate.Engine.IMapping mapping;
private readonly IFormatter formatter;
public void Execute(System.IO.TextWriter script)
{
var mappings = cfg.CreateMappings(dialect);
ScriptObjectsForTables(mappings, script);
}
private void ScriptObjectsForTables(Mappings mappings, TextWriter script)
{
var tables = mappings.IterateTables;
var auditTableBuilder = new AuditTableBuilder();
foreach (Table table in tables)
{
if (table.IsPhysicalTable)
{
var auditTable = auditTableBuilder.BuildAuditTable(table);
ScriptObjectsForTable(table, auditTable, script);
}
}
}
private void ScriptObjectsForTable(Table dataTable, Table auditTable, TextWriter script)
{
ScriptAuditTable(auditTable, script);
ScriptInsertTrigger(dataTable, auditTable, script);
ScriptUpdateTrigger(dataTable, auditTable, script);
ScriptDeleteTrigger(dataTable, auditTable, script);
}
private void ScriptAuditTable(Table auditTable, TextWriter script)
{
string defaultCatalog = NHibernate.Util.PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultCatalog, cfg.Properties, null);
string defaultSchema = NHibernate.Util.PropertiesHelper.GetString(NHibernate.Cfg.Environment.DefaultSchema, cfg.Properties, null);
string sqlCreateString = auditTable.SqlCreateString(dialect, mapping, defaultCatalog, defaultSchema);
script.WriteLine(formatter.Format(sqlCreateString));
var comments = auditTable.SqlCommentStrings(dialect, defaultCatalog, defaultSchema);
foreach (string line in comments)
script.Write(formatter.Format(line));
script.WriteLine(formatter.Format("go")); // create trigger statements must in their own batch
}
private void ScriptInsertTrigger(Table dataTable, Table auditTable, TextWriter script)
{
ScriptTrigger(string.Format("{0}_onInsert", dataTable.Name),
"insert", "'I'", "inserted",
dataTable, auditTable, script);
}
private void ScriptUpdateTrigger(Table dataTable, Table auditTable, TextWriter script)
{
ScriptTrigger(string.Format("{0}_onUpdate", dataTable.Name),
"update", "'U'", "inserted",
dataTable, auditTable, script);
}
private void ScriptDeleteTrigger(Table dataTable, Table auditTable, TextWriter script)
{
ScriptTrigger(string.Format("{0}_onDelete", dataTable.Name),
"delete", "'D'", "deleted",
dataTable, auditTable, script);
}
/// <summary>
/// Scripts out a create trigger sql statement
/// </summary>
/// <param name="triggerName">The name of the trigger</param>
/// <param name="triggerOperation">insert, update, or delete</param>
/// <param name="auditOperationValue">Value to insert for AuditOperation field</param>
/// <param name="triggerTable">The "built-in" trigger table with affected data - inserted or deleted</param>
/// <param name="dataTable"></param>
/// <param name="auditTable"></param>
/// <param name="script"></param>
private void ScriptTrigger(string triggerName, string triggerOperation,
string auditOperationValue, string triggerTable,
Table dataTable, Table auditTable, TextWriter script)
{
Table trigger; // Just to calculate the name of the trigger
trigger = new Table(triggerName);
trigger.Schema = dataTable.Schema;
trigger.Catalog = dataTable.Catalog;
trigger.IsQuoted = dataTable.IsQuoted;
string dataTableName = dataTable.GetQualifiedName(dialect);
string auditTableName = auditTable.GetQualifiedName(dialect);
triggerName = trigger.GetQualifiedName(dialect);
string triggerHeading;
string triggerBody;
triggerHeading = string.Format("create trigger {0} on {1} for {2} as", triggerName, dataTableName, triggerOperation);
triggerBody = string.Format("insert into {0} select *, {1}, {2}, {3} from {4}", auditTableName, TIMESTAMP_DEFAULT, USER_DEFAULT, auditOperationValue, triggerTable);
script.Write(formatter.Format(triggerHeading));
script.Write(formatter.Format("set nocount on"));
script.Write(formatter.Format(triggerBody));
script.WriteLine(formatter.Format("go")); // create trigger statements must in their own batch
}
}
}</pre>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Mapping;
namespace AuditLogExample
{
public class AuditTableBuilder
{
public Table BuildAuditTable(Table dataTable)
{
Table auditTable = new Table(string.Format("Audit_{0}",dataTable.Name));
auditTable.Catalog = dataTable.Catalog;
auditTable.Schema = dataTable.Schema;
auditTable.IsQuoted = dataTable.IsQuoted;
foreach(Column column in dataTable.ColumnIterator)
CopyColumn(column, auditTable);
CopyPrimaryKey(dataTable, auditTable);
AddAuditColumns(auditTable);
return auditTable;
}
private void CopyColumn(Column sourceColumn, Table auditTable)
{
Column newColumn = (Column)sourceColumn.Clone();
auditTable.AddColumn(newColumn);
}
private void CopyPrimaryKey(Table dataTable, Table auditTable)
{
var pk = new PrimaryKey();
foreach (Column sourceColumn in dataTable.PrimaryKey.ColumnIterator)
{
pk.AddColumn(auditTable.Column(sourceColumn.Name));
}
auditTable.PrimaryKey = pk;
}
private void AddAuditColumns(Table auditTable)
{
Column ts = new Column("AuditTimestamp");
ts.SqlType = "datetime";
ts.IsNullable = false;
ts.DefaultValue = AuditScripter.TIMESTAMP_DEFAULT;
auditTable.AddColumn(ts);
auditTable.PrimaryKey.AddColumn(ts);
Column user = new Column("AuditUser");
user.Length = 256; // system_user returns a sysname, which is really nvarchar(256)
user.SqlType = "sysname";
user.IsNullable = false;
user.DefaultValue = AuditScripter.USER_DEFAULT;
auditTable.AddColumn(user);
auditTable.PrimaryKey.AddColumn(user);
Column op = new Column("AuditOperation");
op.SqlType = "char";
op.Length = 1;
op.IsNullable = false;
auditTable.AddColumn(op);
}
}
}</pre>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Mapping;
namespace NHibernate.Mapping
{
public static class TableExtensions
{
public static Column Column(this Table Table, string ColumnName)
{
return Table.ColumnIterator.Where(c => c.Name == ColumnName).FirstOrDefault();
}
}
}</pre>
<p>I have a couple of gotchas and details to explain.</p>
<p>First, this works for me. I’m sure there are edge cases where everything goes horribly wrong. Please let me know when you find them.</p>
<p>Next, CREATE TRIGGER commands are VERY anti-social. They refuse to share a batch with any other statements. That’s why there’s a “go” between everything. In query analyzer (or the SSMS query window now), it starts a fresh batch. </p>
<p>If you know your SQL, this should look pretty simple. Pass an NHibernate configuration to the constructor of AuditScripter, then call Execute. The code loops through all of the physical tables in your configuration, first building a nearly-identical audit table, then creating the three triggers. </p>
<p>The primary key of the audit table has all the fields from the primary key of your data table, plus AuditUser and AuditTimestamp. A single user cannot alter the same record in two different ways at the exact same moment. In fact, I don’t think any two users could, but I’ll let it slide. </p>
<p>The code could probably be improved to automatically include some common indexes on the audit tables.</p>
<p>I’m sure this is the worst possible way to generate code, but I wanted something non-tool specific. I thought about T4 templates since everyone probably has Visual Studio, but this was quicker than figuring out how to get a full NHibernate configuration in to a T4 template. </p>
<h4>Expanding the idea</h4>
<p>You can definitely build on this idea to generate all sorts of repetitive code based on your NHibernate schema. For instance, if you’re unlucky enough to work in a shop with one of those stored-proc crazed database Nazis, this should help quite a bit. You can use this same idea to generate thousands of CRUD stored procedures in a few minutes. </p>
Views and Databases Don't Mix
2009-12-21T00:00:00+00:00
http://jasondentler.com/blog/2009/12/views-and-databases-dont-mix
<h2>The Problem</h2> <p>In my MVC applications, I sometimes bind my views directly to NHibernate entities. a lot. like always. I also do session-per-request. </p> <p>I don’t remember what prompted this thought – probably Twitter – but it seemed questionable to access the database from the view by loading a lazy collection. I knew you shouldn’t put database access <strong><em>code</em></strong> in the view, but this would just be a property, nothing complex at all. <a href="http://ayende.com/Blog/" target="_blank">Ayende</a> set me straight. </p> <blockquote> <p>You should avoid it. It is dangerous to do loading in the <br />view, it is subject to too many changes.</p> </blockquote> <p>How do we prevent it? Of course, the simple answer is “just don’t do it.” Anything more quickly falls in the category of protecting you from yourself, of which I’m usually not a fan. Still, this is easy to overlook. The <a href="http://haacked.com/archive/2005/08/03/DoesMortKnowWeAreTalkingSmackAboutHimBehindHisBack.aspx" target="_blank">Morts</a> of the world – and me - will fall in to this trap easily. </p> <h2>ViewModel Solution</h2> <p>What if we had some sort of model, but instead of being generic for the entire application, it only dealt with the concerns of a specific view. Oh, and what if we called it something weird like viewmodel. </p> <p>This is the best way to avoid problems. Instead of binding directly to an entity, each view should have a corresponding viewmodel class, that contains all of the data being pushed down to the view as well as all the data collected by the view from the user. It’s a POCO specific to the view, with no association to the NHibernate session, so it can’t accidentally load up some data. </p> <p>You can easily test your viewmodels. Since they also make your views pretty darn stupid, you can maybe skip some of that time-consuming UI testing. Well, skip it safely this time. ViewModels also work well for all that validation attribute markup. Just sayin’.</p> <p>This isn’t the point of my post today, and what I’ve described isn’t the traditional Model-View-ViewModel. It’s some weird hybrid of separated presentation patterns. You can read more about view models <a href="http://jeffhandley.com/archive/2008/10/21/viewmodel-pattern.aspx" target="_blank">here</a> and <a href="http://jeffhandley.com/archive/2008/10/27/helloworld.viewmodel.aspx" target="_blank">here</a> and on <a href="http://jfromaniello.blogspot.com/2009/08/nhibernate-and-wpf-viewmodels-and-views.html" target="_blank">Jose’s Chinook Media Manager application series</a>. </p> <h2>Exploding View Solution</h2> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/12/image.png"><img style="border-bottom: 0px; border-left: 0px; margin: 4px 20px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://jasondentler.com/blog/wp-content/uploads/2009/12/image_thumb.png" width="125" height="225" /></a> While I can’t say it’s worse than something silently breaking, I don’t like the idea of something bad silently working. Fragile code only works until the worst possible moment.</p> <p>So, without going for a full ViewModel implementation, I thought it would be a good thing (or at least slightly better) to make NHibernate throw an exception when we hit the DB in the view so we have to fix it now while we’re debugging instead of later. I initially had thoughts about interceptors or connection providers and all sorts of craziness. Ayende’s answer is simply to close the session at the controller boundary. </p> <p>How do we implement this? We close the session between the controller action and the view. So, instead of session per (the entire) request, we trim the scope at the end just a bit. </p> <p>Let’s take a high-level look at a chunk of the <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> lifecycle:</p> <ol> <li>A controller action is chosen based on the request and action filters like HttpGet or HttpPost.</li> <li>The action (the actual controller method) executes, returning an action result – a ViewResult, RedirectToActionResult, ContentResult, or some other built-in or custom action result.</li> <li>The action result executes. In the case of a ViewResult, the view is rendered down to actual HTML and written out to the response stream. </li> </ol> <p>We need to close down the session between #2 and #3. Lucky for us, every controller has an overloadable / overridable method called OnResultExecuting. This method gets called just before the action result is executed. We can simply override this method in our application’s base controller class. You have one of those, right? They’re handy for all sorts of stuff.</p> <p>Just close down any session we may have open inside OnResultExecuting. Considering the references, this takes a little bit of plumbing, but I’ll leave that up to you since it’s dependent on your method of opening and tracking NHibernate sessions through the request. </p> <p></p> <p></p> <h4>One last thing</h4> <p>Maybe in a later version of <a href="http://nhprof.com" target="_blank">NH Profiler</a>, the problem I described today will trigger an alert. Maybe not. </p> <p>If you’re using <a href="http://nhforge.org" target="_blank">NHibernate</a> without NH Profiler, you’re either writing substandard code or wasting time – probably both. If you don’t believe me, download a trial and see what it tells you about your last NHibernate app.</p>
Authentication, Impersonation, and Dynamic NHibernate Connection Strings
2009-11-18T00:00:00+00:00
http://jasondentler.com/blog/2009/11/authentication-impersonation-and-dynamic-nhibernate-connection-strings
<p>A web site I recently worked on has two major parts. The first is internet-facing and allows customers to create data records. The other is for internal use to allow office staff to alter data created by the customer. </p> <h4>SQL Audit Setup</h4> <p>The database uses MS SQL Server trigger-based audit logs to record data changes with a username and timestamp. They are literally for audit purposes, and not used in the application. Every database table has a matching Audit table with exactly the same fields plus a username, change type, and timestamp field. </p> <p>Only updates and deletes trigger an entry in the audit log. The data recorded in the log represents the record prior to the change. The username field is defaulted to SYSTEM_USER, a SQL server specific variable that returns the current account name associated with the connection. This can be either a SQL server account or a windows account. Change type is a single character U or D depending on the action being performed. Timestamp is a datetime field defaulted to GETDATE(). </p> <p>In order to associate audit log records with a particular username, all updates and deletes must run in the context of the user.</p> <h4>Authentication and Impersonation</h4> <p>Customers do not log in to the website. There is no authentication. When a customer interacts with the database, we used a generic SQL account specified in the connection string. All customer changes are recorded with the name of this generic account.</p> <p>When the office staff uses the website, they are required to authenticate with their windows accounts. This account is impersonated all the way to the database so the audit log will record the specific user name. </p> <p>There are several ways to achieve this impersonation. The option I chose to use is basic authentication. Over SSL (an https website) this is just as secure as any other data. The primary drawback is that users will get the standard, generic popup log in box. Since the username and password are transmitted to the web server, the web server can easily impersonate this user to any resource, including SQL, even on another server. </p> <p>You can also run Windows authentication. This was referred to as NTLM back in the day. The benefit of this over basic authentication is that Internet Explorer will authenticate with the web server automatically using the current user’s windows credentials. Since this authentication is done with public keys instead of passwords, the web server can’t impersonate the user to resources (including SQL server) on other servers. This means it’s not really a working solution by itself. If you’re running SQL server on your production web server, stop reading now and go fix that. </p> <p>Fortunately, windows authentication can take advantage of delegated Kerberos authentication. This is difficult to set up and well beyond the scope of this post. Basically, after trading some more public keys around, the SQL server knows that the web server is telling the truth about the current user and agrees to run the SQL statements in the context of that user. Internet Explorer users are still not prompted for their user names and passwords, and it just works.  </p> <p><em><font color="#ff0000">Warning: Impersonation, no matter which method you choose, is not recommended. It effectively disables connection pooling, which stops your application from scaling. In fact, this whole post is probably one bad idea after another. </font></em></p> <p>In this particular case, I’m safe. We can’t physically fit more than a dozen “staff” users, and we’ll certainly never get approval to hire even that many. I’ve used this same architecture for hundreds of users before I knew any better – and the hardware was much slower. In short, it’ll work in this case. </p> <h4>Dynamic Connection Strings</h4> <p>This led to another small issue. Customers should log in with a generic SQL account. Staff should log in with their windows accounts. </p> <p>Jose R. led me to <a href="http://nhforge.org/wikis/howtonh/dynamically-change-user-info-in-connection-string.aspx" target="_blank">this article on the NHForge wiki</a> from November 2008. Well, things have changed slightly in the last year. Also, I wanted something a little more pluggable. </p> <p><a href="http://nhforge.org" target="_blank">NHibernate</a> uses a DriverConnectionProvider to supply it with a connection. To alter the connection string as needed, we only need to override the ConnectionString property of this class. </p> <pre class="brush:csharp">using NHibernate.Connection;
namespace DynamicConnectionStringExample
{
public class DynamicConnectionProvider : DriverConnectionProvider
{
public static IConnectionStringProvider connectionStringProvider;
protected override string ConnectionString
{
get
{
if (null!=connectionStringProvider)
{
return connectionStringProvider.GetConnectionString();
}
return base.ConnectionString;
}
}
}
}</pre>
<p>Note: The example I show here assumes you are using one of the standard bytecode providers such as NHibernate.Bytecode.Castle. However, you could very easily use an IoC bytecode provider (except <a href="http://ninject.org/" target="_blank">Ninject</a>) from uNHAddIns and use constructor dependency injection to inject the IConnectionStringProvider dependency. If not, you’ll need to manually set the ConnectionStringProvider.</p>
<p>To use this, just tell NHibernate about it:</p>
<pre class="brush:csharp">Environment.Properties[Environment.ConnectionProvider] = typeof(DynamicConnectionProvider).AssemblyQualifiedName;</pre>
<p>Of course, the “magic” really happens in the IConnectionStringProvider. If we have an authenticated user, GetConnectionString() returns a connection string with Integrated Security = true. If we don’t, we return one with a SQL username and password.</p>
Simple Domain Events
2009-11-12T00:00:00+00:00
http://jasondentler.com/blog/2009/11/simple-domain-events
<p>This is my first attempt at the <a href="http://martinfowler.com/eaaDev/DomainEvent.html" target="_blank">domain event pattern</a>, so use at your own risk. A lot of this post was <strike>blatantly ripped off from</strike> inspired by <a href="http://www.udidahan.com/2009/06/14/domain-events-salvation/" target="_blank">Udi Dahan’s posts on the same subject</a>. Other bits and pieces come from around the ‘net. Sorry I’m not giving credit. At the time, I was researching a problem, not a blog post.</p> <h4>Your Problem</h4> <p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" border="0" align="left" src="http://blog.lib.umn.edu/biomdoc/access_services/Lily_Tomlin_telephone_operator.jpg" width="223" height="246" />Let’s use the ever-popular “preferred customer” example. You’ve built this beautiful ecommerce application. You even implemented coupon code discounts and stuff. Customers put items in the carts, checkout, and magically get their stuff in 2 to 93.5 days. </p> <p>Today, the sales director emails you about their new “Preferred customer” program. A preferred customer gets an automatic 2% discount on orders over $1000 (up to $20). This will be a piece of cake. You quickly write up a few new tests, slap an IsPreferred boolean property on your customer entity, and build a new order total strategy for this discount scenario. All the tests turn green. </p> <p>Then you naively email him to ask how a customer becomes “preferred.” The sales director replies “After the 20th order over $1000, the customer automatically becomes preferred.” Simple enough. He continues “When that happens, we need to place an order for a complimentary gift basket and the sales rep needs an email about it. Also, any customer with a single order over $20,000 or two orders over $10,000 is automatically enrolled in the program. Next Tuesday, we’re meeting to discuss the new Gold preferred program. I want you there.” </p> <p>Let’s step back and analyze what just happened here. Your beautiful application just got owned by Yet Another Tool With an MBA and you have to share oxygen with him for an hour next Tuesday. More importantly, you have a problem. Even though there are multiple ways to become a preferred customer, the customer only becomes preferred once. They only get one gift basket. Also, you need to do two entirely different actions based on the same event – place a gift basket order and send an email to the sales rep. On top of all that, there’s another mess of weird requirements in the works. How will you handle this without turning your beautiful application in to a pile of ugly hacks? Domain events. </p> <h4>What’s is it?</h4> <p>The domain events pattern is the code equivalent of the office gossip network. Whenever something interesting happens, the office gossip tells anyone and everyone who might care about the news. </p> <p>You have a requirement: “When X happens, do Y1, Y2, Y3, and Y4.” X is the event. The Y’s are the resulting actions that your application should take. There may be one action. There may be 15. There may be none. It doesn’t matter really. Let’s say the event is “John B. Customer just ordered 2 widgets and a sprocket.” Obviously, one of your actions will be “Ship 2 widgets and a sprocket to John B. Customer” You’ll also want to email him a receipt of his order. If this is his first order, you’ll want to mail him a catalog and add him to the mailing list. </p> <p>How would you handle this? Well, you could have your customer’s PlaceOrder method call the services directly. That creates all sorts of tight coupling that you don’t want. Plus the reference is going the wrong direction. You could inject the services and program to an interface, but a lot of people consider that a bad idea. Even with an interface, your entities know more than they need to about your services. </p> <p>You’ll probably want to use domain events for this. Domain events are especially helpful when X could happen in many different places, or the Y’s change a lot. They keep your coupling down by keeping your domain blissfully ignorant.</p> <p>The checkout code of your ecommerce site doesn’t need to know how to ship products, email receipts, or anything else. It just needs to tell some central event dispatcher – the office gossip - “Hey. John B. Customer just placed an order for 2 sprockets and a widget.”</p> <h4>What’s the solution?</h4> <p>Basically, if you understand Pub/Sub service bus, toss out the queue and the transactional stuff. Now you understand the layout of domain events. </p> <p>You have a dispatcher. So that it’s easy to access from anywhere in your application, it’s a static class.</p> <p>You also have some service that wants to know when some event happens. It tells the central dispatcher “Tell me when [particular type of event] happens.” It registers as a handler of that particular type of event.</p> <p>Your domain tells the dispatcher “Hey! This just happened.” The dispatcher looks up the handler or handlers for that event and passes along the message. The handler(s) do some work based on the details of that event. </p> <h4>Another Trio</h4> <p>All of the really cool patterns have 3 parts… and singleton has thick glasses and bad acne. </p> <ol> <li>Events – CustomerBecomesPreferred, CustomerPlacedOrder, etc. Each of these classes will be immutable – they can’t be changed once they’re created. Even though we don’t have any common members, all of our domain events play a particular role in the application. Like Udi says in his post, define role explicitly. All of our event types will implement IDomainEvent. </li> <li>Handlers - In Pub/Sub, these would be the subscribers. You can have multiple handlers for a single type of event. The order that these handlers execute is unknown. For this reason, your events should be immutable. Altering the state of an event during the execution of a handler could create unexpected side-effects in a subsequent handler, and the whole thing becomes a game of <a href="http://en.wikipedia.org/wiki/Chinese_whispers" target="_blank">Chinese Whispers</a>. Since handlers also play a role, we’ll have an interface for them. Each handler will implement IHandle<T> where T is the type of event to be handled. We’ll also define a void Handle(T Event); method so all our handlers have a common entry point for the dispatcher. </li> <li>The dispatcher dispatches events to the various handlers. The internals can be implemented many different ways, but the result is the same. All of the event handlers are registered in the dispatcher. When the dispatcher raises an event, it gets all of the handlers for that type of event. One by one, it executes each handler’s Handle method. We’ll use a service locator internally. <a href="http://ninject.org/" target="_blank">Ninject</a> people will need to use v2.0. </li> </ol> <p>Here’s the diagram:</p> <p><a href="http://yuml.me/diagram/class/[<<IDomainEvent>>{bg:yellow}]^-.-[CustomerBecamePreferred|+Customer;{bg:orange}], [<<IHandle(T)>>{bg:yellow}]<->[note:where T:IDomainEvent{bg:cornsilk}], [<<IHandle(T)>>]^-.-[<<IHandle(CustomerBecamePreferred)>>{bg:yellow}], [<<IHandle(CustomerBecamePreferred)>>]^-.-[SendPreferredGiftBasket|+Handle(CustomerBecamePreferred);{bg:orange}], [<<IHandle(CustomerBecamePreferred)>>]^-.-[SendMessageToSalesRep|+Handle(CustomerBecamePreferred);{bg:orange}], [Dispatcher|+Raise(T event) where T:IDomainEvent{bg:green}]." target="_blank"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" src="http://yuml.me/diagram/class/%5B%3C%3CIDomainEvent%3E%3E%7Bbg%3Ayellow%7D%5D%5E-.-%5BCustomerBecamePreferred%7C+Customer%3B%7Bbg%3Aorange%7D%5D%2C%20%5B%3C%3CIHandle%28T%29%3E%3E%7Bbg%3Ayellow%7D%5D%3C-%3E%5Bnote%3Awhere%20T%3AIDomainEvent%7Bbg%3Acornsilk%7D%5D%2C%20%5B%3C%3CIHandle%28T%29%3E%3E%5D%5E-.-%5B%3C%3CIHandle%28CustomerBecamePreferred%29%3E%3E%7Bbg%3Ayellow%7D%5D%2C%20%5B%3C%3CIHandle%28CustomerBecamePreferred%29%3E%3E%5D%5E-.-%5BSendPreferredGiftBasket%7C+Handle%28CustomerBecamePreferred%29%3B%7Bbg%3Aorange%7D%5D%2C%20%5B%3C%3CIHandle%28CustomerBecamePreferred%29%3E%3E%5D%5E-.-%5BSendMessageToSalesRep%7C+Handle%28CustomerBecamePreferred%29%3B%7Bbg%3Aorange%7D%5D%2C%20%5BDispatcher%7C+Raise%28T%20event%29%20where%20T%3AIDomainEvent%7Bbg%3Agreen%7D%5D" width="640" height="267" /></a></p> <p></p> <p>Here’s the code:</p> <pre class="brush:csharp">namespace DomainEventsSample
{
public interface IDomainEvent
{
}
}
namespace DomainEventsSample
{
public interface IHandle<T> where T:IDomainEvent
{
void Handle(T Event);
}
}
using Microsoft.Practices.ServiceLocation;
namespace DomainEventsSample
{
public static class Dispatcher
{
public static void Initialize(IServiceLocator ServiceLocator)
{
serviceLocator = ServiceLocator;
}
private static IServiceLocator serviceLocator;
static void Raise<T>(T Event) where T : IDomainEvent
{
var handlers = serviceLocator.GetAllInstances<IHandle<T>>();
foreach (var handler in handlers)
{
handler.Handle(Event);
}
}
}
}</pre>
<p>In our main program, we bind some event handlers to their implementations, then make a customer order a bunch of stuff. </p>
<pre class="brush:csharp">using System;
using Ninject;
using Microsoft.Practices.ServiceLocation;
using CommonServiceLocator.NinjectAdapter;
namespace DomainEventsSample
{
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel();
IServiceLocator sl = new NinjectServiceLocator(kernel);
Dispatcher.Initialize(sl);
kernel.Bind<IHandle<CustomerPlacedOrderEvent>>().To<ShipOrder>();
kernel.Bind<IHandle<CustomerBecamePreferred>>().To<SendPreferredGiftBasket>();
kernel.Bind<IHandle<CustomerBecamePreferred>>().To<SendMessageToSalesRep>();
Customer c = new Customer();
for (var i = 0; i < 22; i++)
{
Order newOrder = new Order(1000.00 + i);
c.PlaceOrder(newOrder);
Console.WriteLine("------------------------------------");
}
Console.ReadLine();
}
}
}</pre>
<p>Our events are pretty simple. They just pass along the relevant information. When the event is about something that happened to a customer, we need to know which customer. When the event is about an order, we need to know which order.</p>
<pre class="brush:csharp">namespace DomainEventsSample
{
public class CustomerPlacedOrder:IDomainEvent
{
public CustomerPlacedOrder(Order Order)
{
order = Order;
}
private readonly Order order;
public Order Order
{
get
{
return order;
}
}
}
}</pre>
<p>Here’s a handler. Of course, this is just a stub for some real action you would implement. </p>
<pre class="brush:csharp">using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DomainEventsSample
{
public class ShipOrder : IHandle<CustomerPlacedOrderEvent>
{
#region IHandle<CustomerPlacedOrderEvent> Members
void IHandle<CustomerPlacedOrderEvent>.Handle(CustomerPlacedOrderEvent Event)
{
Console.WriteLine("Shipping order totalling {0:C}",Event.Order.Total);
}
#endregion
}
}</pre>
<h4>Bidirectional Communication</h4>
<p>This is the real reason I’m posting. I had a situation where a domain event handler called in to another system to do some action and the log of that action needed to make its way back to the UI. </p>
<p>Just like with Pub/Sub, domain events are one way. I didn’t want to give up domain events, but I had a requirement I couldn’t fill with the pattern. So, after hacking at it for an afternoon and getting nowhere, I sent out a call for help. Ayende wrote me back. </p>
<blockquote>
<p><font color="#000000">Publish a new event that the UI is listening to</font></p>
</blockquote>
<p>He explains in 10 words what takes me 3 paragraphs. There’s your answer folks. When your handler needs to respond, publish a response event. Simple. Elegant. </p>
<h4>Gimme the Code!</h4>
<p>I’m putting all of the code for this blog in SVN at <a href="http://basiclyeverything.googlecode.com/svn/trunk/" target="_blank">http://basiclyeverything.googlecode.com/svn/trunk/</a></p>
<p>The code for this particular post is in <a href="http://basiclyeverything.googlecode.com/svn/trunk/DomainEventsSample" target="_blank">http://basiclyeverything.googlecode.com/svn/trunk/DomainEventsSample</a></p>
First Impressions: TekPub
2009-10-24T00:00:00+00:00
http://jasondentler.com/blog/2009/10/first-impressions-tekpub
<p>OK Folks. I don’t do endorsements. I especially dislike commercial / corporate training. The trainers aren’t really experts. They didn’t create this stuff. They don’t even use this stuff. They just *teach* this stuff – day after day, city after city. I can learn 95% of the material with my laptop and 15 minutes with the slide deck.</p> <p>What’s the alternative? </p> <p>Blogs? They’re fine for keeping up with trends and knowing what the cool kids are doing, but if you’re trying to learn something from scratch, you’ve got to dig for the good stuff. The worst part about web 2.0 is that any idiot can start a blog about stuff he doesn’t really understand – even me.</p> <p>Books? While I could recommend a few, the honest truth is that I’ve had a dozen queued up on my bookshelf for nearly a year. Even if you do take the time to read, the information is out of date before the book even hits your shopping cart. On top of that, you have no guarantee that the author is really an expert.</p> <p>Here’s something different.</p> <p><img style="border-bottom: 0px; border-left: 0px; margin: 4px 10px 4px 0px; display: inline; border-top: 0px; border-right: 0px" border="0" alt="TekPub_logo " align="left" src="http://blog.tekpub.com/wp-content/uploads/2009/10/TekPub_logo.png" /><a href="http://blog.wekeroad.com/" target="_blank">Rob Connery</a> <a href="http://twitter.com/robconery" target="_blank">@robconery</a> and <a href="http://averyblog.com/" target="_blank">James Avery</a> <a href="http://twitter.com/averyj" target="_blank">@averyj</a> started <a href="http://tekpub.com" target="_blank">TekPub.com</a>. That’s <a href="http://twitter.com/tekpub" target="_blank">@tekpub</a> on Twitter. It’s a library of professional screencast series by Rob, James, and other subject experts with names you’ll recognize. They’re not little 30 minute channel 9 interviews with obscure Microsoft PMs. First, the message is not corporate in any way, shape, or form. Second, the quality is amazing. The audio is clear. The text is crisp and easily readable. The images are both humorous and relevant to the topic.</p> <p>They just launched. Here’s what’s out there already:</p> <ul> <li>Mastering <a href="http://nhforge.org" target="_blank">NHibernate</a> – Oren Eini aka Ayende Rahien and Rob integrate NHibernate with Kona, an MVC storefront app. When it comes to NHibernate, Oren is a true master. </li> <li>Building my own Blog – He’s Rob freakin’ Conery. He’s not setting up WordPress. He’s building a blog from scratch with MVC, lean techniques, AgileZen, BDD, MSpec, and a whole lot of other cool stuff – and taking you along for the ride. </li> <li>Mastering Git – A full 3 hours dedicated to the ins and outs of Git. This will be the first one I watch.</li> <li>Coder to Developer 2009 – Rob updates a classic book in screencast form. This one is free folks, so go watch.</li> <li>Concepts – The first one covers IoC and DI with <a href="http://ninject.org/" target="_blank">Ninject</a>. Again, this one is free. The basics – stuff you should know - are free. This should be pretty awesome for training the new college grad on your team. When you need a break from the training pace, stick him in front of the conference room flat screen with a bucket of popcorn.</li> </ul> <p>Even if you’re cheap, the previews and free stuff are worth a look. Personally, I hope they get Udi Dahan to talk about NServiceBus. </p>
Request for feedback
2009-10-10T00:00:00+00:00
http://jasondentler.com/blog/2009/10/request-for-feedback
<p>Recently, I was asked to provide feedback on someone’s writing about a specific technical subject. Their work is targeted at average .NET programmers who are new to this particular subject – much like I was to <a href="http://nhforge.org" target="_blank">NHibernate</a> just a few months ago. By the time I had finished the 2nd chapter, I was concerned to the point I considered withdrawing from the project. There were some obvious technical flaws, and the whole thing generally rubbed me the wrong way. My feedback was pretty harsh. </p> <p>A week later, I realized my real objections were over the author’s process. He did things exactly backwards from the order I typically follow. He did things in this order because that’s probably how he works, but more importantly because it’s easier to explain. From the other end, he’d have to assume some knowledge that the reader may not have. </p> <p>So as not to sink in to the meta-blogging quicksand, I’ll simply ask these questions about the series up to this point:</p> <ol> <li>Which post(s) did you like the most? Why?</li> <li>Which post(s) did you like the least? Why?</li> <li>How should the process be reordered? Why?</li> <li>What left you generally confused or with unanswered questions?</li> <li>What do you think would be the next logical topic to write about?</li> </ol> <p>Please comment or send me an email with your feedback.</p>
Part 10: Testing and Refactoring
2009-09-20T00:00:00+00:00
http://jasondentler.com/blog/2009/09/part-10-testing-and-refactoring-2
<p><strike>Today’s post will be short</strike>. I’m going to cover the basics of testing with Rhino Mocks and do some refactoring in the DAOs. </p> <p>I’m not an expert. This is just how I do things. If you have a better way, do it your way. Better yet, tell me about it so I can improve the way I work as well.</p> <h3>Testing Terminology</h3> <p>In recent years, testing vocabulary has exploded. There are mocks and stubs and fakes and unit tests and integration tests and acceptance tests and all sorts of jargon. You may be thinking “who cares?” This jargon is only important when code needs to communicate its intent to humans, right?. The compiler doesn’t care what terminology we use. Well, sorry. Code is written for humans, not compilers, so programming jargon is a prerequisite.</p> <h4>Test Doubles</h4> <p>So, let’s go over some common terms. I’m going to lift these definitions straight from Marton Fowler’s <a href="http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs" target="_blank">Mocks Aren’t Stubs</a>. Test Double is a “generic term for any kind of pretend object used in place of a real object for testing purposes.” That’s pretty straight forward. Test doubles come in four types:</p> <blockquote> <ul> <li><b>Dummy</b> objects are passed around but never actually used. Usually they are just used to fill parameter lists. </li> <li><b>Fake</b> objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an <a href="http://www.martinfowler.com/bliki/InMemoryTestDatabase.html">in memory database</a> is a good example). </li> <li><b>Stubs</b> provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'. </li> <li><b>Mocks</b> are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive. </li> </ul> </blockquote> <p>Hi. Still with me? Good. </p> <p>Mocks are significant. They are part of the “proof” of the test. The other three amount to plumbing. Now, you may be asking your self why we even need test doubles. Why can’t we just run our production code and inspect the output? <a href="http://martinfowler.com/articles/mocksArentStubs.html#ClassicalAndMockistTesting" target="_blank">Fowler’s article has several sections</a> about the differences and pros and cons of classical testing (using objects from the real code) vs. mockist testing (creating doubles for everything except what you’re testing).</p> <p>Even in classical testing, you sometimes have to swap in a test double for objects that lead to permanent side effects or operate too slowly. In mockist testing, you swap in test doubles for everything that you’re not explicitly testing. Either way, you need to know how to create and use test doubles.</p> <p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" border="0" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NewRhinoMocksLogo_ECFE/rhinomocks-120x90.png" /></p> <p>We’re going to use <a href="http://ayende.com/projects/rhino-mocks.aspx" target="_blank">Rhino Mocks</a>, a fluent framework for creating stubs and mocks. I don’t know if it’s the best, but if Ayende wrote it, you can bet it’s pretty darn awesome. Plus, the fluent syntax works OK in VB.NET, which is rare. </p> <h3>Writing the Test</h3> <p>Suppose we had a standard GetByID function on our DAO (because we do) containing some code like this (because it does). How would we test that the function actually did what it claimed? </p> <pre class="brush:vbnet"> If m_Session.Transaction Is Nothing OrElse Not m_Session.Transaction.IsActive Then
Dim RetVal As TEntity
Using Tran = m_Session.BeginTransaction
RetVal = m_Session.Get(Of TEntity)(ID)
Tran.Commit()
Return RetVal
End Using
Else
Return m_Session.Get(Of TEntity)(ID)
End If</pre>
<pre class="brush:csharp"> if (null == m_Session.Transaction || !m_Session.Transaction.IsActive)
{
TEntity retval;
using (var Tran = m_Session.BeginTransaction())
{
retval = m_Session.Get<TEntity>(ID);
Tran.Commit();
return retval;
}
}
else
{
return m_Session.Get<TEntity>(ID);
}</pre>
<p>Because I’m not an expert, I won’t try to explain the computer science of testing. I can tell you that if we ignore possible branches inside NHibernate objects, there are two possible paths through our function (the first if we don’t have an existing explicit transaction, and the second if we do), giving us a <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity" target="_blank">cyclomatic complexity</a> of 2. This means that we need two unit tests to achieve 100% code coverage. 100% code coverage doesn’t mean perfect code, but it helps.</p>
<p>I prefer the Record / Playback style of testing. In this style, you start by setting up your expectations within a record section – which mock methods will be called, how many times they’ll be called, in what order they’ll be called, and what their return values should be. Then, in the playback section, you perform the actual action. In this case, we’ll create an instance of our DAO and call its GetByID method. Finally, you verify that the expectations of your mock were met, as well as any other assertions you may need to prove.</p>
<p>Edit: The alternative to Record / Playback is Arrange / Act / Assert. If you don’t know the difference, <a href="http://rasmuskl.dk/post/Why-AAA-style-mocking-is-better-than-Record-Playback.aspx" target="_blank">here’s a good article</a> Jose sent me. Rhino Mocks supports both styles. I still prefer Record / Playback, probably just because I’m used to it.</p>
<p>Here’s what a test of GetByID with a pre-existing transaction would look like:</p>
<pre class="brush:vbnet"> <Test()> _
Public Sub GetByIDTest()
Dim mocks As New MockRepository()
Dim session As NHibernate.ISession = mocks.StrictMock(Of NHibernate.ISession)()
Dim transaction As NHibernate.ITransaction = mocks.Stub(Of NHibernate.ITransaction)()
Dim expected As Student = mocks.Stub(Of Student)()
Dim actual As Student
Using mocks.Record()
Rhino.Mocks.Expect.Call(session.Transaction).Return(transaction).Repeat.Any()
Rhino.Mocks.Expect.Call(transaction.IsActive).Return(True)
Rhino.Mocks.Expect.Call(session.Get(Of Student)(Guid.Empty)).Return(expected)
End Using
Using mocks.Playback()
Dim StudentDao As IReadStudent = New StudentDaoImpl(session)
actual = StudentDao.GetByID(Guid.Empty)
End Using
mocks.VerifyAll()
Assert.IsNotNull(actual, "null entity returned")
Assert.AreSame(expected, actual, "wrong entity returned")
End Sub</pre>
<pre class="brush:csharp"> [Test]
public void GetByIDTest()
{
MockRepository mocks = new MockRepository();
NHibernate.ISession session = mocks.StrictMock<NHibernate.ISession>();
NHibernate.ITransaction transaction = mocks.Stub<NHibernate.ITransaction>();
Student expected = new Student();
Student actual;
using (mocks.Record())
{
Rhino.Mocks.Expect.Call(session.Transaction)
.Return(transaction)
.Repeat.Any();
Rhino.Mocks.Expect.Call(transaction.IsActive)
.Return(true);
Rhino.Mocks.Expect.Call(session.Get<Student>(Guid.Empty))
.Return(expected);
}
using (mocks.Playback())
{
IReadStudent StudentDao = new StudentDAOImpl(session);
actual = StudentDao.GetById(Guid.Empty);
}
mocks.VerifyAll();
Assert.IsNotNull(actual);
Assert.AreSame(expected,actual);
}</pre>
<p>We start by creating a MockRepository. This is the factory for all of our mocks and stubs, controls our record and playback blocks, and verifies that all the mock expectations have been met.</p>
<p>Next, we create a mock of the <a href="http://nhforge.org" target="_blank">NHIbernate</a> session and a stub of an NHibernate transaction. We create a mock because we want to make sure our DAO calls m_Session.Get<>. We also create a double for our return value called expected. We’ll compare it to the actual return value. </p>
<p>Now that we have our doubles, we set up our expectations. We are testing the path of the pre-existing transaction. Session.transaction will return our transaction stub. Since this is a mock, not a stub, the default is to assert that it is called exactly once. Since we’re not interested in this part, we specify that it can be called <strong>any</strong> number of times. We also specify that a call to transaction.IsActive should return true. Finally, we specify that our DAO will call session.Get<> exactly once, and that our mock session should return our expected student.</p>
<p>Next, we start our playback block and perform the action. We create an instance of our DAO, passing in the mock session we wired up in our record block, and we call GetByID. </p>
<p>Finally, we verify that our DAO interacted with the stub as expected. We also assert that the actual instance returned during our test is the same as our expected instance.</p>
<p>This covers the first test. What about the second one? Well, the test would be identical except for your expectations. We would setup our transaction stub so that transaction.IsActive returned false. We would also expect our DAO to call session.BeginTransaction(). </p>
<p>Now, I’m lazy and we’ve already done things backwards by writing our code before our tests, so let’s continue being lazy. I don’t want to write two tests for each DAO method just because of some transaction handling code, which by the way, is repeated all over the place. Not good. Let’s refactor things a bit.</p>
<h3>Refactored Transaction Handling</h3>
<p>In all of the DAO methods, I’ve made the choice to ensure we have an explicit transaction before interacting with the database. In previous versions, each method is nearly identical to the code we tested above above.</p>
<p>In all of this, the only unique code is the call to m_Session.Get(). The rest of the code is just uninteresting transaction handling, and this uninteresting plumbing code is repeated in every method of our DAO. Let’s pull it out in to its own function.</p>
<pre class="brush:vbnet"> Protected Function WrapInTransaction(ByVal F As Func(Of TEntity)) As TEntity
Return WrapInTransaction(Of TEntity)(F)
End Function
Protected Function WrapInTransaction(Of TResult)(ByVal F As Func(Of TResult)) As TResult
If m_Session.Transaction Is Nothing OrElse _
m_Session.Transaction.IsActive = False Then
Using Tran = m_Session.BeginTransaction
Dim RetVal As TResult = F.Invoke()
Tran.Commit()
Return RetVal
End Using
Else
Return F.Invoke()
End If
End Function</pre>
<pre class="brush:csharp"> protected TEntity WrapInTransaction(System.Func<TEntity> F)
{
return WrapInTransaction<TEntity>(F);
}
protected TResult WrapInTransaction<TResult>(System.Func<TResult> F)
{
if (null == m_Session.Transaction || !m_Session.Transaction.IsActive)
{
using (NHibernate.ITransaction Tran = m_Session.BeginTransaction())
{
TResult RetVal = F.Invoke();
Tran.Commit();
return RetVal;
}
}
else
{
return F.Invoke();
}
}</pre>
Now we can pass in the small-but-interesting bit of code as a parameter to the WrapInTransaction method. This lets us simplify our methods down to this:
<pre class="brush:vbnet"> Public Function GetByID(ByVal ID As System.Guid) As TEntity Implements IRead(Of TEntity).GetByID
Return WrapInTransaction(Function() m_Session.Get(Of TEntity)(ID))
End Function</pre>
<pre class="brush:csharp"> public TEntity GetById(System.Guid ID)
{
return WrapInTransaction(() => m_Session.Get<TEntity>(ID));
}</pre>
<p>It’s shorter. Some might argue that it’s not as readable since it uses lambda syntax. In this case, I think DRY (don’t repeat yourself) is more important. To be honest, I’m not sure if this cuts the cyclomatic complexity of our methods in half, but It certainly lets us write about 1/2 as many tests and still have 100% coverage. We just need to write our already-have-a-transaction and wrap-in-transaction tests once period, instead of once per method.</p>
<p>If you’re working in C#, you can create another overload that accepts a System.Action (System.Func but returning void). In Visual Basic.NET, this would be a Sub, but unfortunately, there’s no lambda syntax for calling a Sub in VB.NET. To get around this, I’ve updated our Save method to this:</p>
<pre class="brush:vbnet"> Public Function Save(ByVal Entity As TEntity) As TEntity Implements ISave(Of TEntity).Save
Return WrapInTransaction(Function() SaveOrUpdate(Entity))
End Function
Private Function SaveOrUpdate(ByVal Entity As TEntity) As TEntity
m_Session.SaveOrUpdate(Entity)
Return Entity
End Function</pre>
Since we're returning a value, we can use our existing WrapInTransaction(Func<>) method. The download includes tests for all of our DAO methods, including WrapInTransaction.
<p>That’s it for part 10. For homework, write the tests for our StudentDaoImpl class. Hints: Use a fake, verify that it returns what it should, and verify that it doesn’t return what it shouldn’t.</p>
<p>I’ve changed the SQLiteDatabaseScope to match my previous post, and pulled it in to its own project. </p>
<p>Download the entire solution in <a href="http://jasondentler.com/downloads/NStackExample.Part10.VBNET.zip" target="_blank">VB.NET</a> or <a href="http://jasondentler.com/downloads/NStackExample.Part10.CSharp.zip" target="_blank">C#</a>.</p>
<p>In part 11, we’ll dive in to validation.</p>
<p>Jason</p>
Houston Tech Fest 2009
2009-09-18T00:00:00+00:00
http://jasondentler.com/blog/2009/09/houston-tech-fest-2009
<p>I’ll be attending Houston Tech Fest 2009 next weekend.</p> <ul> <li>ASP.NET MVC in Action - Testing the Last Mile with UI Testing – <a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx" target="_blank">Jimmy Bogard</a></li> <li>ASP.NET MVC in Action - Level 300 - <a href="http://jeffreypalermo.com/" target="_blank">Jeffrey Palermo</a></li> <li>Automated builds & continuous integration – <a href="http://flux88.com/" target="_blank">Ben Scheirman</a> (<a href="http://twitter.com/Subdigital" target="_blank">@Subdigital</a>)</li> <li>Into to NHibernate – <a href="http://scottwhite.blogspot.com/" target="_blank">Scott White</a> (<a href="http://twitter.com/kibbled_bits" target="_blank">@kibbled_bits</a>)</li> </ul> <p>I’m looking forward to meeting some local people I’ve been following online for a while.</p> <p>Also, Houston ALT.NET is <a href="http://flux88.com/blog/workshop-on-continuous-integration-this-saturday/" target="_blank">hosting a CI workshop</a> this Saturday from 9 AM to 2 PM. Unfortunately, I can’t attend. </p>
NHibernate Testing with SQLite in-memory DB
2009-09-14T00:00:00+00:00
http://jasondentler.com/blog/2009/09/nhibernate-testing-with-sqlite-in-memory-db
<p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" border="0" alt="SQLite Logo" align="left" src="http://sqlite.org/images/SQLite.gif" />This is a follow-up to my post <a href="http://jasondentler.com/blog/2009/08/nhibernate-unit-testing-with-sqlite-in-memory-db/" target="_blank">here</a> about SQLiteDatabaseScope, a small class to control the lifecycle of SQLite in-memory databases. It allows you to run NHibernate tests against SQLite’s fast in-memory database. Since each test can have its own database in memory, you can easily run tests in parallel without conflict. </p> <p><em>Warning: While SQLite is thread-safe, SQLiteDatabaseScope itself is not. It is intended to be used to manage one or more SQLite in-memory databases per thread, not shared across threads.</em></p> <p>Since I originally wrote SQLiteDatabaseScope, I’ve learned a few things about <a href="http://sqlite.org" target="_blank">SQLite</a> and <a href="http://nhforge.org" target="_blank">NHibernate</a>, and updated the code to match. </p> <p>First, building an NHibernate configuration and session factory is heavy. It’s a huge waste of time to rebuild those objects for each new instance of the database. Instead, you supply your own configuration and session factory.</p> <p>Second, it’s possible to create an in-memory database with initial data. A few people I follow on Twitter mentioned giving up on SQLite because they couldn’t quickly and easily fill the in-memory database with necessary initial test data. I’ve found a solution. We attach a SQLite file database containing our data, perform an “INSERT INTO tbl SELECT * FROM attached.tbl” command for each table, then detach our file database. The import runs fast, and the file database can be safely accessed by multiple threads simultaneously, so we can still run our tests in parallel. Better yet, since SQLite doesn’t support foreign keys, we don’t have to be careful about the table order when we import.</p> <p>Here’s the code:</p> <pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SQLite;
namespace System.Data.SQLite
{
public class SQLiteDatabaseScope : IDisposable
{
private const string CONNECTION_STRING = "Data Source=:memory:;Version=3;New=True;";
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SQLiteDatabaseScope));
private object sync = new object();
private NHibernate.Cfg.Configuration config;
private NHibernate.ISessionFactory sessionFactory;
private string initialDataFilename;
private SQLiteConnection connection;
public SQLiteDatabaseScope(NHibernate.Cfg.Configuration Configuration,
NHibernate.ISessionFactory SessionFactory)
{
Log.Info("Creating database scope");
config = Configuration;
sessionFactory = SessionFactory;
}
public SQLiteDatabaseScope(NHibernate.Cfg.Configuration Configuration,
NHibernate.ISessionFactory SessionFactory,
string InitialDataFilename)
: this(Configuration, SessionFactory)
{
initialDataFilename = InitialDataFilename;
}
public NHibernate.ISession OpenSession()
{
return sessionFactory.OpenSession(GetConnection());
}
public NHibernate.ISession OpenSession(NHibernate.IInterceptor Interceptor)
{
return sessionFactory.OpenSession(GetConnection(), Interceptor);
}
public NHibernate.IStatelessSession OpenStatelessSession()
{
return sessionFactory.OpenStatelessSession(GetConnection());
}
private SQLiteConnection GetConnection()
{
if (null == connection)
BuildConnection();
return connection;
}
private void BuildConnection()
{
Log.Info("Building SQLite database connection");
connection = new SQLiteConnection(CONNECTION_STRING);
connection.Open();
BuildSchema();
if (!string.IsNullOrEmpty(initialDataFilename))
new SQLiteDataLoader(connection, initialDataFilename).ImportData();
}
private void BuildSchema()
{
Log.Debug("Creating schema");
NHibernate.Tool.hbm2ddl.SchemaExport se;
se = new NHibernate.Tool.hbm2ddl.SchemaExport(config);
se.Execute(false, true, false, connection, null);
}
private bool disposedValue = false;
protected void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
Log.Info("Disposing database scope.");
if (null != connection)
{
connection.Dispose();
}
}
}
this.disposedValue=true;
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}</pre>
<pre class="brush:csharp">using System;
using System.Linq;
using System.Data;
using System.Data.SQLite;
namespace System.Data.SQLite
{
public class SQLiteDataLoader
{
private static log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SQLiteDataLoader));
private const string ATTACHED_DB = "zxcvbnmInitialData";
private SQLiteConnection connection;
private string initialDataFilename;
public SQLiteDataLoader(SQLiteConnection Connection,
string InitialDataFilename)
{
connection = Connection;
initialDataFilename = InitialDataFilename;
}
public void ImportData()
{
DataTable dt = connection.GetSchema(SQLiteMetaDataCollectionNames.Tables);
var tableNames = (from DataRow R in dt.Rows
select (string)R["TABLE_NAME"]).ToArray();
AttachDatabase();
foreach (string tableName in tableNames)
{
CopyTableData(tableName);
}
DetachDatabase();
}
private void AttachDatabase()
{
SQLiteCommand cmd = new SQLiteCommand(connection);
cmd.CommandText = String.Format("ATTACH '{0}' AS {1}", initialDataFilename, ATTACHED_DB);
Log.Debug(cmd.CommandText);
cmd.ExecuteNonQuery();
}
private void DetachDatabase()
{
SQLiteCommand cmd = new SQLiteCommand(connection);
cmd.CommandText = string.Format("DETACH {0}", ATTACHED_DB);
Log.Debug(cmd.CommandText);
cmd.ExecuteNonQuery();
}
private void CopyTableData(string TableName)
{
int rowsAffected;
SQLiteCommand cmd = new SQLiteCommand(connection);
cmd.CommandText = string.Format("INSERT INTO {0} SELECT * FROM {1}.{0}", TableName, ATTACHED_DB );
Log.Debug(cmd.CommandText);
rowsAffected = cmd.ExecuteNonQuery();
Log.InfoFormat("{0} {1} rows loaded", rowsAffected, TableName);
}
}
}</pre>
<p></p>
<p>Jason</p>
<p>- We now return you to your regularly scheduled program.</p>
World's Newest Micro-ISV
2009-09-12T00:00:00+00:00
http://jasondentler.com/blog/2009/09/worlds-newest-micro-isv
<p>Today, I started the world’s newest Micro-ISV. It may be several months before I share any details, but the journey started today.</p>
Part 9: NHibernate transactions
2009-09-08T00:00:00+00:00
http://jasondentler.com/blog/2009/09/part-9-nhibernate-transactions
<p>In this part, we’re going to wrap our <a href="http://nhforge.org" target="_blank">NHibernate</a> transactions and create a factory for them so we can use them in higher layers without referencing NHibernate all the way up.</p> <p>If you’re new to the series, you can read <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">Part 1</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">Part 2</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">Part 3</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4/" target="_blank">Part 4</a>, <a href="http://jasondentler.com/blog/2009/08/part-5-fixing-the-broken-stuff/" target="_blank">Part 5</a>, <a href="http://jasondentler.com/blog/2009/08/part-6-ninject-and-mvc-or-how-to-be-a-web-ninja/" target="_blank">Part 6</a>, <a href="http://jasondentler.com/blog/2009/08/part-7-nhibernate-and-ninject-for-asp-net-mvc/" target="_blank">Part 7</a>, and <a href="http://jasondentler.com/blog/2009/09/part-8-daos-repositories-or-query-objects" target="_blank">Part 8</a> to catch up.</p> <p>You may have noticed in part 8 that in each DAO method, if we didn’t already have an explicit transaction, I created one around each database interaction. My reason for this is explained in Ayende’s NHibernate Profiler alert “<a href="http://nhprof.com/Learn/Alert?name=DoNotUseImplicitTransactions" target="_blank">Use of implicit transactions is discouraged</a>.” This works great for simple DB interaction, but what about the more complex scenarios? </p> <p>This is where we get to talk about this great thing called a business transaction. So once again, I’m going to parade out my experts. Actually, this time it’s only Udi Dahan. There are two key points he’s written about on his blog. </p> <ol> <li><a href="http://www.udidahan.com/2009/01/24/ddd-many-to-many-object-relational-mapping/" target="_blank">Partial failures can be good</a>. The programmer in all of us sees that and screams <a href="http://en.wikipedia.org/wiki/ACID" target="_blank">atomicity</a>. Transactions  should be all-or-nothing. Anything less is just wrong. Right? In real life, there are instances where we allow, and even prefer partial failures of business transactions. Udi gives us a great example. Would you leave the grocery store empty handed simply because they were out of one item on your list? Probably not. When you’re gathering requirements, be sure to ask questions about the proper way to fail. “Roll it all back” isn’t the only option. </li> <li><a href="http://www.udidahan.com/2007/01/22/realistic-concurrency/" target="_blank">Realistic Concurrency</a> – The entire post is worth reading, but Udi makes one point I want to touch on specifically. When performing an operation for the user, you should get the current state, validate, and then perform the task all within the business transaction. </li> </ol> <p>Let’s use our college application as an example. We have a user story / use case / requirement / story card / whatever to allow students to register for classes, provided those classes aren’t full. If you’ve ever worked at or attended a college or university where certain classes always have more demand than available seats, you are no doubt aware of how quickly those classes will fill up. In fact, the best sections (best professors and best times) can fill up just minutes after registration is opened. It’s very possible that dozens of potential students could access the section when there is only a few seats left. Since the enrollment in a particular section (the current state) changes so rapidly, you must obtain a lock, refresh your enrollment numbers and make sure there is room (revalidate) before actually enrolling that student. If more than one registration request is received, they should be performed serially. </p> <p>The process is:</p> <ol> <li>Open a transaction at the proper <a href="http://en.wikipedia.org/wiki/Isolation_(database_systems)" target="_blank">isolation level</a>. Consult your nearest DBA, as isolation levels are outside the scope of this series. </li> <li>Refresh – Get the current state of the entity </li> <li>(Re)Validate – Be sure the business transaction is still valid for the current state </li> <li>Execute – Perform the insert / update / delete </li> <li>Commit the transaction </li> </ol> <p>Now that we’ve covered business transactions, let’s get set up to use them in our business logic. We shouldn’t have NHibernate types floating around at that level, so we’ll wrap them. Once again, the interfaces go in the Data namespace of the core project and the implementations go in the Data project.</p> <pre class="brush:vbnet">Imports System.Data
Namespace Data
Public Interface ITransactionFactory
Function BeginTransaction() As ITransaction
Function BeginTransaction(ByVal IsolationLevel As IsolationLevel) As ITransaction
End Interface
End Namespace
Namespace Data
Public Interface ITransaction
Inherits IDisposable
Sub Commit()
Sub Rollback()
End Interface
End Namespace
Imports NHibernate
Public Class TransactionFactoryImpl
Implements ITransactionFactory
Public Sub New(ByVal Session As ISession)
m_Session = Session
End Sub
Protected ReadOnly m_Session As ISession
Public Function BeginTransaction() As ITransaction Implements ITransactionFactory.BeginTransaction
Return New TransactionWrapper(m_Session.BeginTransaction)
End Function
Public Function BeginTransaction(ByVal IsolationLevel As System.Data.IsolationLevel) As ITransaction Implements ITransactionFactory.BeginTransaction
Return New TransactionWrapper(m_Session.BeginTransaction(IsolationLevel))
End Function
End Class
Imports NHibernate
Public Class TransactionWrapper
Implements ITransaction
Public Sub New(ByVal Transaction As NHibernate.ITransaction)
m_Transaction = Transaction
End Sub
Protected ReadOnly m_Transaction As NHibernate.ITransaction
Public Sub Commit() Implements ITransaction.Commit
m_Transaction.Commit()
End Sub
Public Sub Rollback() Implements ITransaction.Rollback
m_Transaction.Rollback()
End Sub
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free other state (managed objects).
m_Transaction.Dispose()
End If
' TODO: free your own state (unmanaged objects).
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class</pre>
<pre class="brush:csharp">using System.Data;
namespace NStackExample.Data
{
public interface ITransactionFactory
{
ITransaction BeginTransaction();
ITransaction BeginTransaction(IsolationLevel isolationLevel);
}
}
using System;
namespace NStackExample.Data
{
public interface ITransaction : IDisposable
{
void Commit();
void Rollback();
}
}
using System.Data;
using NHibernate;
namespace NStackExample.Data
{
public class TransactionFactoryImpl : ITransactionFactory
{
public TransactionFactoryImpl(ISession Session)
{
m_Session = Session;
}
protected readonly ISession m_Session;
#region ITransactionFactory Members
public ITransaction BeginTransaction()
{
return new TransactionWrapper(m_Session.BeginTransaction());
}
public ITransaction BeginTransaction(IsolationLevel isolationLevel)
{
return new TransactionWrapper(m_Session.BeginTransaction(isolationLevel));
}
#endregion
}
}
using System;
using NHibernate;
namespace NStackExample.Data
{
public class TransactionWrapper : ITransaction
{
public TransactionWrapper(NHibernate.ITransaction Transaction)
{
m_Transaction = Transaction;
}
protected readonly NHibernate.ITransaction m_Transaction;
#region ITransaction Members
void ITransaction.Commit()
{
m_Transaction.Commit();
}
void ITransaction.Rollback()
{
m_Transaction.Rollback();
}
private bool disposedValue = false;
protected override void Dispose(bool Disposing)
{
if (!this.disposedValue)
{
m_Transaction.Dispose();
}
this.disposedValue = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}</pre>
<p>You may be interested to know that the NHibernate ITransaction will perform an implicit rollback when it is disposed, unless an explicit call to Commit or Rollback has already occurred. To implement this behavior, we implement IDisposable in our transaction wrapper and chain our wrapper’s Dispose to NHibernate.ITransaction’s Dispose. This implicit rollback can indicate a missing call to Commit, so it <a href="http://nhprof.com/Learn/Alert?name=AvoidImplicitRollback" target="_blank">generates an alert in NHibernate Profiler</a>. If you intend to rollback, do it explicitly. Your code will be easier to understand.</p>
<p>That’s it for part 9.</p>
<p>Jason
<br />- Off to mow the lawn.</p>
Part 8: DAOs, Repositories, or Query Objects
2009-09-05T00:00:00+00:00
http://jasondentler.com/blog/2009/09/part-8-daos-repositories-or-query-objects
<p>Part 8 is about abstracting <a href="http://nhforge.org" target="_blank">NHibernate</a>. Catch up by reading <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">Part 1</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">Part 2</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">Part 3</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4/" target="_blank">Part 4</a>, <a href="http://jasondentler.com/blog/2009/08/part-5-fixing-the-broken-stuff/" target="_blank">Part 5</a>, <a href="http://jasondentler.com/blog/2009/08/part-6-ninject-and-mvc-or-how-to-be-a-web-ninja/" target="_blank">Part 6</a>, and <a href="http://jasondentler.com/blog/2009/08/part-7-nhibernate-and-ninject-for-asp-net-mvc/" target="_blank">Part 7</a>. </p> <div><em><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" border="0" align="left" src="http://commons.wikimedia.org/w/thumb.php?f=Nuvola%20apps%20important%20yellow.svg&width=200px" width="100" height="84" />Warning: This post will contain an extraordinary number of links. They will lead you to the opinions of very smart people™. Click them. Read them. Learn something new.</em></div> <div>There is no one best practice. I know. I googled for it. It seems there are just as many patterns as there are anti-patterns. In fact, these days we’re not even clear <a href="http://msdn.microsoft.com/en-us/library/aa973811.aspx" target="_blank">which</a> is <a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx" target="_blank">which</a>. There are <a href="http://codebetter.com/blogs/gregyoung/archive/2009/04/23/repository-is-dead-long-live-repository.aspx" target="_blank">differing opinions</a> all <a href="http://www.udidahan.com/2007/03/28/query-objects-vs-methods-on-a-repository/" target="_blank">over</a> the <a href="http://geekswithblogs.net/Billy/archive/2006/02/15/69607.aspx" target="_blank">place</a>.</div> <h3>What are my options?</h3> <p><a href="http://martinfowler.com/eaaCatalog/repository.html" target="_blank">Repositories</a></p> <ul> <li><a href="http://twitter.com/sbohlen" target="_blank">Steve Bohlen</a> uses the repository pattern. </li> <li><a href="http://twitter.com/jfroma" target="_blank">José Romaniello</a> <a href="http://jfromaniello.blogspot.com/2009/08/chinook-media-manager-core.html" target="_blank">uses repositories</a> in his Chinook Media Manager sample on NHForge.org </li> <li><a href="http://twitter.com/ayende" target="_blank">Ayende</a> <a href="http://msdn.microsoft.com/en-us/library/aa973811.aspx" target="_blank">loved repositories in 2006</a>, but not anymore. </li> </ul> <p><a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" target="_blank">Data Access Objects</a>:</p> <ul> <li><a href="http://fabiomaulo.blogspot.com/" target="_blank">Fabio Maulo</a> <a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx#30272" target="_blank">uses DAOs</a> with query objects. </li> <li><a href="http://twitter.com/tehlike" target="_blank">Tuna Toksoz</a> uses DAOs with FindBy methods </li> </ul> <p><a href="http://martinfowler.com/eaaCatalog/queryObject.html" target="_blank">Query objects</a>:</p> <li>In early 2009, Ayende posted that he <a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx" target="_blank">no longer likes repositories,</a> and has switched to query objects which expose raw NHibernate  ICriteria. </li> <li><a href="http://twitter.com/udidahan" target="_blank">Udi Dahan</a> also prefers <a href="http://www.udidahan.com/2007/03/28/query-objects-vs-methods-on-a-repository/" target="_blank">query objects</a> <p>One note about all of this: Repositories and DAOs can both be used with query objects or simple FindBy methods. Query objects can also be used on their own.</p> <h3>What’s the score? </h3> <p>The experts don’t agree, so use whatever you think will work best for your application and your team. By the way, if you’re not following all of these people on twitter, go follow them now.</p> <p>If you’re looking for a good NHibernate repository sample, check out <a href="http://nhforge.org/wikis/howtonh/your-first-nhibernate-based-application.aspx" target="_blank">Your First NHibernate based application</a> by Gabriel Schenker on the NHForge wiki, or José’s Chinook WPF app. </p> <p>In this sample application, we’re going to use Data Access Objects. The pattern is simple and well known. This application is small and we won’t have many queries, so we’ll use DAOs with FindBy methods. In a large project, such as an ERP, I would use query objects. </p> <h3>Splitting the CRUD</h3> <p>CRUD stands for create, read/retrieve, update, and delete/destroy. which correspond to SQL INSERT, SELECT, UPDATE, and DELETE respectively. </p> <p>Suppose we’re tracking down an issue in our system where the customer’s middle name was being erased from the database. You start with the most likely locations such as the round trip through the customer update view. No luck. You’ll have to dig in deeper.</p> <p>We’re using constructor dependency injection throughout our application. Our DAO is defined by the interface IDAO<T>. If you saw some object with a dependency of IDAO<Customer>, you would assume that it performs some database action on customer, so it would be a candidate for deeper investigation. Of course, without diving in to the code, you wouldn’t know what it actually does to customer. </p> <p>As it turns out 95% of the uses of IDAO<Customer> only display customer data. They don’t actually change anything. You just wasted a LOT of time digging through code that couldn’t possibly cause your bug.</p> <p>Now suppose you had split your IDAO interface to allow more fine-grained dependencies. Instead of IDAO<T>, you now have ICreate<T>, IRead<T>, IUpdate<T>, and IDelete<T>. When searching for a bug like the one I described, you only need to search through classes with dependencies on IUpdate<Customer> and possibly ICreate<Customer>. </p> <p>We’re tracking which entity instances are transient (new, not saved) and which ones are already persisted (saved to the database) by the ID property. If the ID is equal to Guid.Empty, the instance is transient. If the ID has any other value, it’s persistent. Since we know that handy bit of information, we don’t really need separate interfaces for create and update operations. We can combine them in to one called ISave<T>. We now have IRead<T>, ISave<T>, and IDelete<T>. </p> <p>Even though we’ve split our interface up by operation, we’re still only going to have one DAO implementation. In the <a href="http://ninject.org/" target="_blank">Ninject</a> module, we’ll bind each of our three interfaces to the DAO implementation.</p> <p>Every entity has the same basic CUD, but what about entity-specific queries? In these cases, we’ll create entity-specific interfaces such as IReadCustomer. This means you could have up to four IoC bindings for each entity. </p> <p>Splitting the CRUD operations in to separate interfaces has one added benefit. In our case, we don’t want to allow certain (most) entities to be deleted. In these cases, your entity-specific DAO shouldn’t implement IDelete. For this reason, we won’t implement deletes in our generic base DAO.</p> <h3>Show me some code already!</h3> <p>We put our interfaces in the data namespace of the core project and our implementations in the data project.</p> <pre class="brush:vbnet">Namespace Data
Public Interface IRead(Of TEntity As Entity)
Function GetByID(ByVal ID As Guid) As TEntity
End Interface
End Namespace
Namespace Data
Public Interface ISave(Of TEntity As Entity)
Function Save(ByVal Entity As TEntity) As TEntity
End Interface
End Namespace
Namespace Data
Public Interface IDelete(Of TEntity As Entity)
Sub Delete(ByVal Entity As TEntity)
End Interface
End Namespace
Namespace Data
Public Interface IReadStudent
Inherits IRead(Of Student)
Function FindByStudentID(ByVal StudentID As String) As Student
Function FindByName(ByVal LikeFirstName As String, ByVal LikeLastName As String) As IEnumerable(Of Student)
End Interface
End Namespace
Imports NHibernate
Public Class GenericDAOImpl(Of TEntity As Entity)
Implements IRead(Of TEntity)
Implements ISave(Of TEntity)
Public Sub New(ByVal Session As ISession)
m_session = Session
End Sub
Protected ReadOnly m_Session As ISession
Public Function GetByID(ByVal ID As System.Guid) As TEntity Implements IRead(Of TEntity).GetByID
If m_Session.Transaction Is Nothing Then
Dim RetVal As TEntity
Using Tran = m_Session.BeginTransaction
RetVal = m_Session.Get(Of TEntity)(ID)
Tran.Commit()
Return RetVal
End Using
Else
Return m_Session.Get(Of TEntity)(ID)
End If
End Function
Public Function Save(ByVal Entity As TEntity) As TEntity Implements ISave(Of TEntity).Save
If m_Session.Transaction Is Nothing Then
Using Tran = m_Session.BeginTransaction
m_Session.SaveOrUpdate(Entity)
Tran.Commit()
End Using
Else
m_Session.SaveOrUpdate(Entity)
End If
Return Entity
End Function
End Class
Imports NHibernate
Imports NHibernate.Criterion
Public Class StudentDaoImpl
Inherits GenericDAOImpl(Of Student)
Implements IReadStudent
Public Sub New(ByVal Session As ISession)
MyBase.New(Session)
End Sub
Public Function FindByName(ByVal LikeFirstName As String, ByVal LikeLastName As String) As System.Collections.Generic.IEnumerable(Of Student) Implements IReadStudent.FindByName
Dim crit As ICriteria = m_Session.CreateCriteria(Of Student) _
.Add(Expression.Like("FirstName", LikeFirstName)) _
.Add(Expression.Like("LastName", LikeLastName)) _
.SetMaxResults(101)
If m_Session.Transaction Is Nothing Then
Using Tran = m_Session.BeginTransaction()
Dim RetVal = crit.List.Cast(Of Student)()
Tran.Commit()
Return RetVal
End Using
Else
Return crit.List.Cast(Of Student)()
End If
End Function
Public Function FindByStudentID(ByVal StudentID As String) As Student Implements IReadStudent.FindByStudentID
Dim Crit = m_Session.CreateCriteria(Of Student) _
.Add(Expression.Eq("StudentID", StudentID))
If m_Session.Transaction Is Nothing Then
Using Tran = m_Session.BeginTransaction
Dim RetVal = Crit.UniqueResult(Of Student)()
Tran.Commit()
Return RetVal
End Using
Else
Return Crit.UniqueResult(Of Student)()
End If
End Function
End Class</pre>
<pre class="brush:csharp">using System;
namespace NStackExample.Data
{
public interface IRead<TEntity> where TEntity : Entity
{
TEntity GetById(Guid ID);
}
}
namespace NStackExample.Data
{
public interface ISave<TEntity> where TEntity : Entity
{
TEntity Save(TEntity entity);
}
}
namespace NStackExample.Data
{
public interface IDelete<TEntity> where TEntity:Entity
{
void Delete(TEntity entity);
}
}
using System.Collections.Generic;
namespace NStackExample.Data
{
public interface IReadStudent : IRead<Student>
{
Student FindByStudentID(string StudentID);
IEnumerable<Student> FindByName(string LikeFirstName, string LikeLastName);
}
}
using NHibernate;
namespace NStackExample.Data
{
public class GenericDAOImpl<TEntity> : IRead<TEntity>, ISave<TEntity> where TEntity : Entity
{
public GenericDAOImpl(ISession Session)
{
m_Session = Session;
}
protected readonly ISession m_Session;
public TEntity GetByID(System.Guid ID)
{
if (m_Session.Transaction == null)
{
TEntity retval;
using (var Tran = m_Session.BeginTransaction())
{
retval = m_Session.Get<TEntity>(ID);
Tran.Commit();
return retval;
}
}
else
{
return m_Session.Get<TEntity>(ID);
}
}
public TEntity Save(TEntity Entity)
{
if (m_Session.Transaction == null)
{
using (var Tran = m_Session.BeginTransaction())
{
m_Session.SaveOrUpdate(Entity);
Tran.Commit();
}
}
else
{
m_Session.SaveOrUpdate(Entity);
}
return Entity;
}
}
}
using NHibernate;
using NHibernate.Criterion;
using System.Collections.Generic;
using System.Linq;
namespace NStackExample.Data
{
public class StudentDAOImpl : GenericDAOImpl<Student>, IReadStudent
{
public StudentDAOImpl(ISession Session) : base(Session) { }
public System.Collections.Generic.IEnumerable<Student> FindByName(string LikeFirstName, string LikeLastName)
{
ICriteria crit = m_Session.CreateCriteria<Student>()
.Add(Expression.Like("FirstName", LikeFirstName))
.Add(Expression.Like("LastName", LikeLastName))
.SetMaxResults(101);
if (m_Session.Transaction == null)
{
using (var Tran = m_Session.BeginTransaction())
{
var RetVal = crit.List().Cast<Student>();
Tran.Commit();
return RetVal;
}
}
else
{
return crit.List().Cast<Student>();
}
}
public Student FindByStudentID(string StudentID)
{
var Crit = m_Session.CreateCriteria<Student>()
.Add(Expression.Eq("StudentID", StudentID));
if (m_Session.Transaction == null)
{
using (var Tran = m_Session.BeginTransaction())
{
var RetVal = Crit.UniqueResult<Student>();
Tran.Commit();
return RetVal;
}
}
else
{
return Crit.UniqueResult<Student>();
}
}
}
}</pre>
<p></p>
<h3>Other changes</h3>
<p>I’ve cleaned out the course and student DAO junk from part 7. These were just used to illustrate session-per-request. </p>
<p>The fluent mapping classes have been moved in to a mapping folder.</p>
<p></p>
<p>That’s it for part 8. Don’t forget to write your tests for the queries. </p>
<p>Jason
<br />- IBlog.Post(Part8) operation completed. Executing IWatchTV.Watch(Timespan.FromHours(1))</p>
<p></p>
</li>
Part 7: NHibernate and Ninject for ASP.NET MVC
2009-08-29T00:00:00+00:00
http://jasondentler.com/blog/2009/08/part-7-nhibernate-and-ninject-for-asp-net-mvc
<p>In <a href="http://jasondentler.com/blog/2009/08/part-6-ninject-and-mvc-or-how-to-be-a-web-ninja/" target="_blank">part 6</a>, I explained how to set up <a href="http://ninject.org/" target="_blank">Ninject</a> with <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a>. In this part, we’ll add <a href="http://nhforge.org" target="_blank">NHibernate</a> to the mix. Specifically, we’re going to set up session-per-request using a Ninject and bind all the necessary NHibernate interfaces.</p> <p>Of course, for the sake of history, read up on <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">part 1</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">part 2</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">part 3</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4/" target="_blank">part 4</a>, <a href="http://jasondentler.com/blog/2009/08/part-5-fixing-the-broken-stuff/" target="_blank">part 5</a>, and <a href="http://jasondentler.com/blog/2009/08/part-6-ninject-and-mvc-or-how-to-be-a-web-ninja/" target="_blank">part 6</a>. <img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" border="0" align="left" src="http://nhforge.org/cfs-file.ashx/__key/CommunityServer.Components.SiteFiles/logos/NHLogoSmall.gif" width="240" height="56" /></p> <p>If you aren’t familiar with NHibernate in an ASP.NET MVC application, the most common way to manage your sessions is to open one session per web request. Just about everything you need to know about session-per-request is explained in the content and comments of <a href="http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx" target="_blank">this post</a> on Ayende’s blog, but I’ll summarize for you.</p> <ul> <li>While building a session factory may be a big operation, once it’s built, opening a session is lightweight. </li> <li>Opening a session does not open a connection to the database </li> <li>NHibernate has a built in method for doing session-per-request, but Ayende doesn’t use it for simple stuff and neither will we. When your application doesn’t do anything other than session-per-request, it’s just easier to do it this way. </li> <li>Multiple business transactions and therefore multiple sessions in a single web request are usually not necessary, just because of how users tend to interact with the application. Even then, you can usually accomplish the same thing with multiple DB transactions on the same session. </li> </ul> <p><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" border="0" alt="SessionPerConversation" align="left" src="http://nhforge.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate/SessionPerConversation_5F00_thumb_5F00_7345BC5F.png" width="240" height="172" /></p> <p>NHibernate Burrow is available to help with complex session management in web apps where session per conversation is used. Basically, this allows you to span your NHibernate sessions across several web requests. Just a quick note: If you disregarded everyone’s advice and used Identity (integer auto-number) ID fields, Burrow won’t work for you. If you want more information, check out the Burrow posts on NHForge. Also,  <a href="http://nhforge.org/blogs/nhibernate/archive/2009/08/15/nhibernate-and-wpf-models-concept.aspx" target="_blank">Jose Romaniello’s uses Conversation per Business Transaction</a> in his NHibernate and WPF series on NHForge.org. It’s definitely worth a read.</p> <p>OK. Back to session-per-request. I’m taking a slightly different approach than Ayende. Even though opening a session is lightweight, I don’t like the idea of opening a session for requests that may not use NHibernate at all. For example, in an application I’m building at work, only about 7 views out of nearly 50 actually use an NHibernate session. That’s a lot of unused sessions. </p> <p>First things first, we need to make a Ninject module for all of our NHibernate bindings. Where are we going to put it? We have two options. We could put it in NStackExample.Data with all of our NHibernate mappings and configuration. We could also put it in NStackExample.Web. Like Ayende, we will be storing the NHibernate session in the context of the current web request and relying on our application’s EndRequest event to close the session. Since we’re unfortunately coupled to the web application, we’ll put it in the web project. </p> <ol> <li>In the web project, make a new folder called Code. </li> <li>Make a class in that folder called NHibernateModule. </li> <li>NHibernateModule should inherit from Ninject.Core.StandardModule. </li> </ol> <p>The process of configuring NHibernate is a lot of work and only needs to be done once. Since our configuration object also creates the session factory, another potentially heavy operation, we kill two birds with one stone. The binding for our NHibernate configuration looks like this:</p> <pre class="brush:vbnet"> Public Overrides Sub Load()
Dim Cfg As New NStackExample.Data.Configuration
Cfg.Configure()
Bind(Of NStackExample.Data.Configuration).ToConstant(Cfg)
End Sub</pre>
<pre class="brush:csharp""> public override void Load()
{
NStackExample.Data.Configuration Cfg = new NStackExample.Data.Configuration()
Cfg.Configure();
Bind<nstackexample.data.configuration>().ToConstant(Cfg);
}</pre>
<p>ToConstant bindings essentially create singletons, at least within the scope of our Ninject kernel. Unlike true singletons, this isn’t evil because our tests are free to mock, replace, and re-implement them as necessary. </p>
<p>Now that we have NHibernate configured and our session factory built, we need to bind our NHibernate session. The scope of our session is somewhat complex (per-request). We could use the OnePerRequestBehavior of Ninject, but that <a href="http://stackoverflow.com/questions/536007/ninject-oneperrequestbehaviour-doesnt-seem-to-work-correctly" target="_blank">requires the registration of an IIS HTTP module</a>. Instead, we’ll just bind it to a method and manage it ourselves. This method will create up to one session per request. If a particular request doesn’t require a session, Ninject will never call the method, so an unnecessary session won’t be created. If a particular request asks for a session more than once, perhaps to build more than one DAO, the method will create a single session and use it throughout the web request. Here’s what our module looks like with the binding for our session:</p>
<pre class="brush:vbnet"> Friend Const SESSION_KEY As String = "NHibernate.ISession"
Public Overrides Sub Load()
Dim Cfg As New Configuration
Cfg.Configure()
Bind(Of Configuration).ToConstant(Cfg)
Bind(Of NHibernate.ISession).ToMethod(AddressOf GetRequestSession)
End Sub
Private Function GetRequestSession(ByVal Ctx As IContext) As NHibernate.ISession
Dim Dict As IDictionary = HttpContext.Current.Items
Dim Session As NHibernate.ISession
If Not Dict.Contains(SESSION_KEY) Then
'Create an NHibernate session for this request
Session = Ctx.Kernel.Get(Of Configuration)().OpenSession()
Dict.Add(SESSION_KEY, Session)
Else
'Re-use the NHibernate session for this request
Session = Dict(SESSION_KEY)
End If
Return Session
End Function</pre>
<pre class="brush:csharp"> internal const string SESSION_KEY = "NHibernate.ISession";
public override void Load()
{
Configuration Cfg = new Configuration();
Cfg.Configure();
Bind<Configuration>().ToConstant(Cfg);
Bind<NHibernate.ISession>().ToMethod(x => GetRequestSession(x));
}
private NHibernate.ISession GetRequestSession(IContext Ctx)
{
IDictionary Dict = HttpContext.Current.Items;
NHibernate.ISession Session;
if (!Dict.Contains(SESSION_KEY))
{
// Create an NHibernate session for this request
Session = Ctx.Kernel.Get<Configuration>().OpenSession();
Dict.Add(SESSION_KEY, Session);
} else {
// Re-use the NHibernate session for this request
Session = (NHibernate.ISession) Dict[SESSION_KEY];
}
return Session;
}</pre>
<p>All we have left to do is dispose our session at the end of the request. Let's go back to the Global.asax codebehind.</p>
<pre class="brush:vbnet"> Private Sub MvcApplication_EndRequest(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.EndRequest
If Context.Items.Contains(NHibernateModule.SESSION_KEY) Then
Dim Session As NHibernate.ISession = Context.Items(NHibernateModule.SESSION_KEY)
Session.Dispose()
Context.Items(NHibernateModule.SESSION_KEY) = Nothing
End If
End Sub</pre>
<pre class="brush:csharp"> public MvcApplication()
{
this.EndRequest += MvcApplication_EndRequest;
}
private void MvcApplication_EndRequest(object sender, System.EventArgs e)
{
if (Context.Items.Contains(NHibernateModule.SESSION_KEY))
{
NHibernate.ISession Session = (NHibernate.ISession) Context.Items[NHibernateModule.SESSION_KEY];
Session.Dispose();
Context.Items[NHibernateModule.SESSION_KEY] = null;
}
}</pre>
<p>To illustrate how this will work, I’ve made several additions to the code download. I’ve added a BaseController and HomeController so we can begin to run our web application. I’ve also added a IStudentDao and ICourseDao interfaces to the core project and corresponding implementations in the Data project. I’ve bound the DAO interfaces to their corresponding implementations and added debug statements to output exactly what’s happening with our session. Finally, I’ve set up a constructor in HomeController making it dependent on IStudentDao and ICourseDao. </p>
<p>When we run our application, we see from the debug output that the session is created when we create our IStudentDao. The session is reused to create our ICourseDao. This gives us everything we need to create the HomeController. The web request executes. When the request ends, the session is disposed. If you remove one of the Dao dependencies from HomeController, you’ll see that our session is created. It’s not reused because nothing else needs a session. If you remove both of the Dao dependencies from HomeController, you’ll see that our session is never even created. Since we didn’t create a session, we don’t dispose it when the web request ends.</p>
<p>That’s all for part 7. In part 8, we’ll wrap the NHibernate transaction for use in our controllers project and build a real DAO or two. </p>
<p>Get your code here! We have <a href="http://www.jasondentler.com/downloads/NStackExample.Part7.VBNET.zip" target="_blank">VB.NET</a> and <a href="http://www.jasondentler.com/downloads/NStackExample.Part7.CSharp.zip" target="_blank">CSharp</a> flavored bits. </p>
<p>Jason
<br />- NHibernating Ninja Wannabe</p>
Part 6: Ninject and MVC or How to be a Web Ninja
2009-08-28T00:00:00+00:00
http://jasondentler.com/blog/2009/08/part-6-ninject-and-mvc-or-how-to-be-a-web-ninja
<p><img style="border-right-width: 0px; margin: 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="Ninject" align="left" src="http://kohari.org/wp-content/themes/thesis_151/custom/images/ninject-logo.png" />Nope. I don’t mean <a href="http://askaninja.com/" target="_blank">this guy</a>. He’s cool – well, maybe, maybe not - but I was thinking less comedic assassin and more dependency injection (DI.) <a href="http://ninject.org/" target="_blank">Ninject</a> is the illegitimate brain child of <a href="http://kohari.org/" target="_blank">Nate Kohari</a>, and the subject of today’s post. For those of you looking for another NHibernate fix, we’ll set up session-per-request in part 7.</p> <p>If you’re new here, you can check out <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">Part 1</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">Part 2</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">Part 3</a>, <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4/" target="_blank">Part 4</a>, and <a href="http://jasondentler.com/blog/2009/08/part-5-fixing-the-broken-stuff/" target="_blank">Part 5</a> to catch up. Grab the latest source from the end of Part 5.</p> <p>If you remember back in the part 1, I said we’d be using Ninject v1. I lied. We’ll be using v1.5. This is the version built by <a href="http://groups.google.co.uk/group/horn-development" target="_blank">horn</a>, and the version that includes Ninject.Framework.MVC.dll. Save yourself some time. Go get the source for horn, build it, and then let horn build Ninject, Fluent NHibernate, and MVCContrib. </p> <p>Let’s talk about Ninject’s constructor dependency injection. Say you have an AccountBuilder object that builds up a user account object from some fields on a “new user” form and saves it to the database. That’s a pretty complicated task for just one object. You should split off the persistence responsibility to a DAO or Repository and the password hashing / encryption to a password service. The AccountBuilder doesn’t care how the DAO saves the data, just that it does. It also doesn’t care how the password is secured. AccountBuilder has a dependency on each of these services. If ever there was a time to code to interfaces, this is it. The constructor looks like this:</p> <pre class="brush:vbnet">Public Sub New(DAO As ISaveUserAccounts, PwdHasher As IHashPasswords)</pre>
<pre class="brush:csharp">public AccountBuilder(ISaveUserAccounts DAO, IHashPasswords PwdHasher)</pre>
<p>The details of the constructor aren’t important, only the signature. AccountBuilder is a concrete type, meaning we can create an instance of it, so Ninject can auto self-bind it. We don’t have to tell Ninject ahead of time that it will be creating an AccountBuilder for us. When we ask Ninject to get an AccountBuilder for us, it checks to see if it has a binding for it (more on that in a minute). Since it doesn’t, it checks to see if it can create an object of type AccountBuilder. Since AccountBuilder isn’t abstract (MustInherit in VB.NET) or an interface, Ninject decides that it will just create an AccountBuilder for us. </p>
<p>it goes through all the constructors searching for one with the Inject attribute or the one with the most parameters. Once it’s decided on a constructor, it tries to resolve each of those parameters. Let’s say for a minute that instead of the interfaces, we had specified the actual concrete implementations as parameters. Ninject would resolve each of those the same way it is resolving AccountBuilder. It goes on and on recursively as deep as necessary to resolve each and every dependency until it has instances of DAO and PasswordHasher to use as parameters for the AccountBuilder constructor. Finally, it calls the constructor with those parameters and gives us our AccountBuilder. </p>
<p>Now, because we’ve coded to interfaces, we have to tell Ninject exactly which implementation of those interfaces we want to use. So, we tell Ninject that each time anything needs an ISaveUserAccounts, build up a new instance of UserAccountDAO. It has to be a new instance each time, because UserAccountDAO depends on NHibernate.ISession, which isn’t constant throughout the application. We’ll bind ISession to a Ninject provider. You’ll see an example of that in our application in part 7. The binding for ISaveUserAccounts looks like this:</p>
<pre class="brush:vbnet"> Bind(Of ISaveUserAccounts).To(Of UserAccountDAO)()</pre>
<pre class="brush:csharp"> Bind<ISaveUserAccounts>().To<UserAccountDAO>();</pre>
<p>The password hasher service can be handled a little differently. Let’s suppose for a minute that encryption algorithms can be fairly heavy-weight. We don’t want to build the algorithm over and over, possibly thousands or millions of times an hour on a popular site. Even if it doesn’t bring the site to a screeching halt, it would slow it down significantly. Since the algorithm is reusable, we’re only going to build one for our entire application. Of course, your first thought is “the evil singleton anti-pattern.” Would I do that to you? Well yes, but not intentionally. We are going to create an instance of our PasswordHasher and tell Ninject to pass it out anytime our application needs an implementation of IHashPasswords. The binding looks like this:</p>
<pre class="brush:vbnet"> Bind(Of IHashPasswords).ToConstant(New PasswordHasher)()</pre>
<pre class="brush:csharp"> Bind<IHashPasswords>().ToConstant(New PasswordHasher());</pre>
<p>Of course, if you use just one instance across your entire web, WPF, or multi-threaded application, PasswordHasher will almost certainly need to be thread-safe, but that’s another series of posts. </p>
<p>Now that Ninject knows what implementations to use for those parameters of our AccountBuilder constructor, it builds a new UserAccountDAO, grabs our one-and-only instance of PasswordHasher, calls the constructor and gives us our AccountBuilder. Of course, this is still a pretty basic example.</p>
<p>Now let’s look at <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a>. Up to this point in the series, we’ve talked a lot about the model. Now it’s time to talk about controllers. Controllers in an MVC application manage the flow of your application from view to view, call in to the model to perform actions, and pass data between the model and the views. </p>
<p>Suppose our AccountBuilder is actually a service consumed by our Account controller to carry out the work of registering a new user account. If you’re new to this, you may think that we’re just going to somehow pass in the Ninject kernel to our controller and get our AccountBuilder from there. While I don’t recommend it, you can do that. You’ll essentially end up with the ServiceLocator pattern. We’re going to take this to what may seem an illogical or even perverse extreme. Why not let Ninject build your controllers and inject all of your dependencies? You won’t have any ServiceLocator clutter in your controllers. At least as far as user code goes, the controller is near the bottom of the call stack. You’re in this perfect world where EVERYTHING is injected for you. Let that sink in for a minute. You don’t have to new up a single service ever again. Just ask for it in the constructor wherever you need it. Of course, that’s an absolute and absolutes are evil for the same reason singletons are – you can’t easily prove them with tests. </p>
<p>But wait, doesn’t ASP.NET MVC build the controllers? Yes it does, but it doesn’t have to. Deep inside the mother ship, apparently while hiding from that guy who invented the sealed keyword, <a href="http://haacked.com" target="_blank">Haacked</a> and Co.  built all sorts of extension points in to ASP.NET MVC. One of these extension points happens to be the ability to replace the default controller factory using ControllerBuilder.Current.SetControllerFactory. Just supply the type of your new controller factory implementation. </p>
<p>So, you set up a controller factory to resolve the controllers using Ninject and register all of your controllers with the kernel, right? Wrong. Well, not exactly. Ninject.Framework.MVC has all of that pre-built for you – just use it. Ninject actually has an implementation of HttpApplication that will set up all of this for you. In your Global.asax codebehind file, inherit from Ninject.Framework.Mvc.NinjectHttpApplication. You’ll still have to register your routes. You also have to build the Ninject kernel with all of your ninject modules. </p>
<p>A ninject module is a class that sets up your bindings. So for instance, if you have a module for binding your DAO interfaces to their implementations, it might look something like this:</p>
<pre class="brush:vbnet">Public Class DaoModule
Inherits StandardModule
Public Overrides Sub Load()
Bind(Of ISaveUserAccounts)().To(Of UserAccountDao)()
Bind(Of ILookupUserAccounts)().To(Of UserAccountDao)()
Bind(Of IUserAccountDao)().To(Of UserAccountDao)()
Bind(Of ISaveContacts)().To(Of ContactDao)()
' and so on...
End Sub
End Class</pre>
<pre class="brush:csharp">public class DaoModule : StandardModule
{
public override void Load()
{
Bind<ISaveUserAccounts>().To<UserAccountDAO>();
Bind<ILookupUserAccounts>().To<UserAccountDAO>();
Bind<IUserAccountDao>().To<UserAccountDAO>();
Bind<ISaveContacts>().To<ContactDAO>();
// and so on...
}
}</pre>
<p>Of course, we haven’t built any DAOs to bind yet. We haven’t built any controllers to bind yet either. That brings up another point. If there is a single point of constant change during the development of your application, it will most likely be the controllers. Will you always remember to bind new controllers as you build them? Yeah, neither will I. Wouldn’t it be nice if Ninject just went looking for them instead? That’s exactly what AutoControllerModule is for. Just point it at an assembly. It will find all of your controllers and wire them in to Ninject and its controller factory. </p>
<p>At this stage, our Global.asax codebehind looks something like this:</p>
<pre class="brush:vbnet">Imports Ninject.Framework.Mvc
Imports Ninject.Core
Public Class MvcApplication
Inherits NinjectHttpApplication
Protected Overrides Function CreateKernel() As Ninject.Core.IKernel
Dim ControllerModule As New AutoControllerModule( _
GetType(NStackExample.Controllers.BaseController).Assembly)
Dim Kernel As IKernel = New StandardKernel(ControllerModule)
Return Kernel
End Function
Protected Overrides Sub RegisterRoutes(ByVal routes As System.Web.Routing.RouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
' MapRoute takes the following parameters, in order:
' (1) Route name
' (2) URL with parameters
' (3) Parameter defaults
routes.MapRoute( _
"Default", _
"{controller}/{action}/{id}", _
New With {.controller = "Home", .action = "Index", .id = ""} _
)
End Sub
End Class</pre>
<p>If you don’t want Ninject invading your application that deeply, with a good understanding of Ninject and controller factories, you can easily do all of this by hand. Still, I’m pretty confident Nate wrote better code and tests than most of us would have. </p>
<p>That’s it for part 6. In part 7, we’ll wire up <a href="http://nhforge.org" target="_blank">NHibernate</a> to Ninject, talk about our options for session handling in a web app, and set up session-per-request. With a bit of luck, part 7 will be out this weekend.  </p>
<p>Once again, these are just my practices, not necessarily best practices. As always, feedback welcome, flames by appointment only. </p>
<p>Jason
<br />- 6 down, 52 to go. maybe. </p>
Fluent NHibernate v1 released
2009-08-28T00:00:00+00:00
http://jasondentler.com/blog/2009/08/fluent-nhibernate-v1-released
<p><a href="http://nhforge.org/blogs/nhibernate/archive/2009/08/29/fluent-nhibernate-1-0.aspx" target="_blank">Fluent NHibernate v1 was just released</a>. Congratulations to James Gregory and the rest of the FNH team. </p>
Fluent NHibernate upgrade to v1 RC gotchas
2009-08-26T00:00:00+00:00
http://jasondentler.com/blog/2009/08/fluent-nhibernate-upgrade-to-v1-rc-gotchas
<p>In a project I’m doing at work, I have a rather large table-per-subclass hierarchy. When I upgraded the reference to Fluent NHibernate v1 RC, it immediately broke. This was expected. Many of the mapping method names have been shortened. For example, WithLengthOf is now just Length. ColumnName is now just Column. I think this is great. </p> <p>One thing I wasn’t expecting was the change in JoinedSubclass. The method is deprecated. It still works –mostly. Since the issues this causes are pretty obscure, I’m trying to get the word out to save someone else the same headaches. Isn’t that what a programming blog is really about? I mean, besides all that other stuff like fame and riches.</p> <p>There are two issues:</p> <ol> <li>The newly deprecated JoinedSubclass ignores mappings without mapped properties. This was an issue for me since I had two mapped classes that inherited all of their properties from the base class but implemented their own behavior. After the upgrade, neither of these were included in my mapping. To correct this, upgrade to SubclassMap – everywhere (see #2). </li> <li>You cannot mix JoinedSubclass with the new SubclassMap in the same <a href="http://nhforge.org" target="_blank">NHibernate</a> configuration. JoinedSubclass messes up some internal state with SubclassMap. If you use both, you will get an incomplete configuration exception with a null reference exception inside. </li> </ol> <p>#2 was especially bad for me because I assumed the exception was because I was using SubclassMap incorrectly. I rolled back my code twice before deciding just to go for it. When I replaced my last JoinedSubclass it all magically started working. </p>
First Impression: Horn
2009-08-22T00:00:00+00:00
http://jasondentler.com/blog/2009/08/first-impression-horn
<p>Horn is an open source project used to build other often-interdependent open source projects, such as <a href="http://nhforge.org" target="_blank">NHibernate</a>, Fluent NHibernate, NHContrib, the Castle suite of projects, MVCContrib, Rhino Tools, and Ninject. </p> <p>This solves a couple of very common problems when working with the average ALT.NET stack. </p> <ul> <li>The dependency tree of the ALT.NET stack is a wind-whipped, gnarled, stunted cedar growing out of the side of a rock cliff. It twists and turns back on itself. It would be a monumental task to grab the correct version of all of these, whether that’s the latest trunk or a stable release, sort out the dependencies, and build them all by hand. </li> <li>The precompiled releases of these projects don’t necessarily correspond to each other. NHContrib Validator might depend on a recent nightly build of NH while FNH v1 RC might depend on NH 2.1 GA. </li> <li>Many of these projects have multi-step build processes. It’s not just a simple “F5” build. There may be codegen tasks, unit tests, assembly signing or any number of oddities. </li> </ul> <p>When I published the first part of my series about setting up the solution, there was an issue where the assembly for <a href="http://ninject.org/" target="_blank">Ninject</a>’s ASP.NET MVC integration was only available from the trunk. I posted in the comments that the readers could either wait for me to post the source, including all the 3rd party libraries, or they could grab the source from the trunk and build it themselves. </p> <p>The next day, I got a series of tweets from <a href="http://devlicio.us/blogs/tuna_toksoz" target="_blank">Tuna</a> (<a href="http://www.twitter.com/tehlike" target="_blank">@tehlike</a>) and <a href="http://www.twitter.com/dagda1" target="_blank">@dagda1</a> about <a href="http://groups.google.co.uk/group/horn-development" target="_blank">Horn</a>, so I read up on it. It looked cool, but I had just spent the afternoon updating everything and writing about it, so I was a bit burned out. Now that it’s been two weeks, there are a couple of projects in the stack that need to be updated. FNH released v1 RC (Congratulations James!) and Ninject and MVCContrib also have some updates. </p> <p>I also have two medium sized web apps at work that should be updated to the latest and greatest when we move them from a VPC to a physical server next month. I’m hoping Horn will save me from .NET’s version of DLL HELL. </p> <p>If you want more info, check out the <a href="http://groups.google.co.uk/group/horn-development" target="_blank">discussion group</a>, or just grab the <a href="http://code.google.com/p/hornget/" target="_blank">source code</a>. Horn even has its own <a href="http://code.google.com/p/horn-contrib/" target="_blank">contrib project</a>. </p> <p>Here are my thoughts:</p> <p>Very first impression – It’s an awesome idea, but it needs a lot more SEO. To find it, I had to search in Google code. Hopefully, this post will help with that. If you’ve got a blog (and you should) and you use Horn, write about it. It deserves great press.</p> <p>I grabbed the latest source from their Google Code SVN. In the /src directory, there’s a hornbuild.bat. I fired up a command prompt, changed directories and ran it. 20 seconds later, I had it - /src/build/net-3.5/debug/horn.exe. </p> <p>From there, I started grabbing everything I needed</p> <pre>horn –install:fluentnhibernate
horn -install:ninject
horn -install:mvccontrib</pre>
<p>Well, that’s what I had planned. I got a BadImageException on SharpSvn when trying to grab FNH. After trying a few things on my own, I tweeted for help. <a href="http://devlicio.us/blogs/tuna_toksoz" target="_blank">Tuna</a>, who I’ve decided is either stalking me or involved in every .NET open source project out there, suggested checking the assemblies with the corflags utility. If you’re new to corflags, like I was, it’s in C:Program FilesMicrosoft SDKsWindowsv6.0ABin and part of the Windows SDK. As it turns out, horn.exe and horn.core.dll in my particular build were not marked as 32-bit. I marked them both as 32-bit with these commands:</p>
<pre>corflags horn.exe /32BIT+
corflags horn.core.dll /32BIT+</pre>
<p>I tried it again. Success! It started by grabbing the castle project, then built it. Then it moved on the NHibernate, and finally Fluent NHibernate. </p>
<p>In the end, the only project out of the three that didn’t work 100% was Ninject. The build for it’s monorail integration had an issue signing the assembly. Since I’m not using monorail, much less Ninject’s monorail integration, I commented that out of the .build file and tried it again. It worked perfectly.</p>
<p>Horn is still a little rough around the edges. For example, when a build fails, horn crashes out to windows error reporting. Even with those issues, it has saved me a lot of time. It’s a great idea and even at this early stage, it’s an amazing tool.</p>
<p>Thanks again to Tuna for answering my stupid questions.</p>
Bidirectional One-to-many with Orphan Delete
2009-08-22T00:00:00+00:00
http://jasondentler.com/blog/2009/08/bidirectional-one-to-many-with-orphan-delete
<p>Here’s the full write-up on my issue from part 5. Since we’re saying all orphan children should be deleted, it seems logical that our DB schema won’t allow orphaned children, meaning Child.Parent_id should have a NOT NULL constraint. However, when I add this constraint and try to do a cascading orphan delete, <a href="http://nhforge.org" target="_blank">NHibernate</a> yells at me because I’ve set the Child.Parent to null / nothing.</p> <p>If I remove this constraint (not good DB practice in my opinion), we see that the orphan is deleted without ever updating Child.Parent_id to NULL, so it won’t violate any database constraints, as far as I can tell.</p> <p>Here’s the code in VB:</p> <pre class="brush:vbnet">Imports FluentNHibernate.Mapping
Imports NUnit.Framework
Public Class Parent
Inherits Entity
Private m_Children As ICollection(Of Child) = New HashSet(Of Child)
Public Overridable Property Children() As ICollection(Of Child)
Get
Return m_Children
End Get
Protected Set(ByVal value As ICollection(Of Child))
m_Children = value
End Set
End Property
End Class
Public Class Child
Inherits Entity
Private m_Parent As Parent
Public Overridable Property Parent() As Parent
Get
Return m_Parent
End Get
Set(ByVal value As Parent)
m_Parent = value
End Set
End Property
End Class
Public Class ParentMapping
Inherits ClassMap(Of Parent)
Public Sub New()
Id(Function(x As Parent) x.ID).GeneratedBy.GuidComb()
HasMany(Function(x As Parent) x.Children) _
.AsSet() _
.WithForeignKeyConstraintName("ParentChildren") _
.Cascade.AllDeleteOrphan() _
.Inverse()
End Sub
End Class
Public Class ChildMapping
Inherits ClassMap(Of Child)
Public Sub New()
Id(Function(x As Child) x.ID).GeneratedBy.GuidComb()
References(Function(x As Child) x.Parent) _
.Cascade.All() _
.WithForeignKey("ChildParent") _
.Not.Nullable()
End Sub
End Class
<TestFixture()> _
Public Class ParentMappingTests
Inherits BaseFixture
<Test()> _
Public Sub CanCascadeSaveFromParentToChild()
Dim ID As Guid
Dim P As Parent
Dim C As Child
Using Scope As New SQLiteDatabaseScope(Of ParentMapping)
Using Session = Scope.OpenSession
Using Tran = Session.BeginTransaction
P = New Parent
'Add a child of the parent
C = New Child With {.Parent = P}
P.Children.Add(C)
ID = Session.Save(P)
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
P = Session.Get(Of Parent)(ID)
Assert.IsNotNull(P)
Assert.AreEqual(ID, P.ID)
Assert.AreEqual(1, P.Children.Count)
Assert.AreNotSame(C, P.Children(0))
Assert.AreEqual(C, P.Children(0))
Assert.AreSame(P.Children(0).Parent, P)
Tran.Commit()
End Using
End Using
End Using
End Sub
<Test()> _
Public Sub CanDeleteOrphanFromParentToChildren()
Dim ID As Guid
Dim P As Parent
Dim C As Child
Using Scope As New SQLiteDatabaseScope(Of ParentMapping)
Using Session = Scope.OpenSession
Using Tran = Session.BeginTransaction
P = New Parent
'Add a child of the parent
C = New Child With {.Parent = P}
P.Children.Add(C)
ID = Session.Save(P)
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
P = Session.Get(Of Parent)(ID)
Assert.IsNotNull(P)
Assert.AreEqual(ID, P.ID)
Assert.AreEqual(1, P.Children.Count)
Assert.AreNotSame(C, P.Children(0))
Assert.AreEqual(C, P.Children(0))
Assert.AreSame(P.Children(0).Parent, P)
Tran.Commit()
End Using
Session.Clear()
'Orphan the child
C = P.Children(0)
P.Children.Remove(C)
C.Parent = Nothing
Using Tran = Session.BeginTransaction
'Orhpaned child should be deleted
Session.SaveOrUpdate(P)
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
P = Session.Get(Of Parent)(ID)
Assert.AreEqual(0, P.Children.Count)
Tran.Commit()
End Using
End Using
End Using
End Sub
End Class</pre>
<p>Here’s the code in C#:</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using FluentNHibernate.Mapping;
using NUnit.Framework;
namespace NStackExample.Data.Tests
{
public class Parent : Entity
{
private ICollection<Child> m_Children = new HashSet<Child>();
public virtual ICollection<Child> Children
{
get { return m_Children; }
protected set { m_Children = value; }
}
}
public class Child : Entity
{
private Parent m_Parent;
public virtual Parent Parent
{
get { return m_Parent; }
set { m_Parent = value; }
}
}
public class ParentMapping : ClassMap<Parent>
{
public ParentMapping()
{
Id((Parent x) => x.ID).GeneratedBy.GuidComb();
HasMany((Parent x) => x.Children)
.AsSet()
.WithForeignKeyConstraintName("ParentChildren")
.Cascade.AllDeleteOrphan()
.Inverse();
}
}
public class ChildMapping : ClassMap<Child>
{
public ChildMapping()
{
Id((Child x) => x.ID).GeneratedBy.GuidComb();
References((Child x) => x.Parent)
.Cascade.All()
.WithForeignKey("ChildParent")
.Not.Nullable();
}
}
[TestFixture()]
public class ParentMappingTests
{
[Test()]
public void CanCascadeSaveFromParentToChild()
{
Guid ID;
Parent P;
Child C;
using (SQLiteDatabaseScope<ParentMapping> Scope = new SQLiteDatabaseScope<ParentMapping>())
{
using (ISession Session = Scope.OpenSession())
{
using (ITransaction Tran = Session.BeginTransaction())
{
P = new Parent();
//Add a child of the parent
C = new Child { Parent = P };
P.Children.Add(C);
ID = (Guid) Session.Save(P);
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction())
{
P = Session.Get<Parent>(ID);
Assert.IsNotNull(P);
Assert.AreEqual(ID, P.ID);
Assert.AreEqual(1, P.Children.Count);
Assert.AreNotSame(C, P.Children.First());
Assert.AreEqual(C.ID , P.Children.First().ID );
Assert.AreSame(P.Children.First().Parent, P);
Tran.Commit();
}
}
}
}
[Test()]
public void CanDeleteOrphanFromParentToChildren()
{
Guid ID;
Parent P;
Child C;
using (SQLiteDatabaseScope<ParentMapping> Scope = new SQLiteDatabaseScope<ParentMapping>())
{
using (ISession Session = Scope.OpenSession())
{
using (ITransaction Tran = Session.BeginTransaction())
{
P = new Parent();
//Add a child of the parent
C = new Child { Parent = P };
P.Children.Add(C);
ID = (Guid) Session.Save(P);
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction())
{
P = Session.Get<Parent>(ID);
Assert.IsNotNull(P);
Assert.AreEqual(ID, P.ID);
Assert.AreEqual(1, P.Children.Count);
Assert.AreNotSame(C, P.Children.First());
Assert.AreEqual(C.ID, P.Children.First().ID );
Assert.AreSame(P.Children.First().Parent, P);
Tran.Commit();
}
Session.Clear();
//Orphan the child
C = P.Children.First();
P.Children.Remove(C);
C.Parent = null;
using (ITransaction Tran = Session.BeginTransaction())
{
//Orhpaned child should be deleted
Session.SaveOrUpdate(P);
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction())
{
P = Session.Get<Parent>(ID);
Assert.AreEqual(0, P.Children.Count);
Tran.Commit();
}
}
}
}
}
}</pre>
Part 5: Fixing the Broken Stuff
2009-08-20T00:00:00+00:00
http://jasondentler.com/blog/2009/08/part-5-fixing-the-broken-stuff
<p>This is part 5 of my series on <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> with <a href="http://nhforge.org" target="_blank">NHibernate</a>. So far, we concentrated on NHibernate and persistence concerns. In this part, we’re going to correct our model and mappings to pass our tests. This will be the last full-time NHibernate post for a while. The next part will be focused on integrating <a href="http://ninject.org/" target="_blank">Ninject</a>, our inversion of control / dependency injection framework, with ASP.NET MVC.</p> <p>If you’re just joining us, you can still catch up.</p> <ul> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">Part 1</a> – Solution setup </li> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">Part 2</a> – Model design </li> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">Part 3</a> – Persistence mapping </li> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4/" target="_blank">Part 4</a> – Persistence tests <a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/LogoNH.gif"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="LogoNH" border="0" alt="LogoNH" align="right" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/LogoNH_thumb.gif" width="43" height="40" /></a> </li> </ul> <p>First, some trivia. According to Fabio Maulo, the NHibernate logo is probably a sleeping <a href="http://en.wikipedia.org/wiki/Marmot" target="_blank">marmot</a>.    </p> <h3>Know what you’re fixing</h3> <p>When correcting bugs, you should correct only bugs. This seems obvious. Yes, we write tests so we can find out what’s broken. The less obvious purpose is to know what’s not broken.</p> <p><strong>Confession</strong>: Sometimes I code first, then test. Sometimes I put on my pants, then my shirt. As long as you leave the house fully dressed, the order isn’t all that important. As long as you write your code and tests every day, the order isn’t all that important.</p> <p>Now, when you’re on a team working on a project, I assume things *should* work a little different. I wouldn’t know. My project team is just me, and I’ve picked up a lot of bad habits from my team over the years.</p> <p>Here are the results of the NUnit tests from part 4: 2 passed, 3 failed, 5 threw exceptions. 2 out of 10 is actually pretty good for me. Let’s work through these 8 problems one at a time.</p> <p> </p> <h3>Bare-minimum NHibernate debugging</h3> <p>NHibernate makes extensive use of the log4net log framework. It’s quick and painless to expose this log to NUni or most other test runners.</p> <ol> <li>In your data test project, add a reference to log4net.dll </li> <li>Add an app.config </li> <li>Add a new class called BaseFixture </li> <li>Set all of your test fixtures to inherit from the base fixture. </li> </ol> <p>Here’s what your app.config should look like with the log4net configuration:</p> <pre class="brush:xml"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<appender name="Debugger" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<logger name="NHibernate.SQL">
<level value="ALL"/>
<appender-ref ref="Debugger"/>
</logger>
</log4net>
</configuration></pre>
<p>Here’s the code for BaseFixture.</p>
<pre class="brush:vbnet">Public MustInherit Class BaseFixture
Protected Shared ReadOnly Log As log4net.ILog = GetLogger()
Private Shared Function GetLogger() As log4net.ILog
log4net.Config.XmlConfigurator.Configure()
Return log4net.LogManager.GetLogger(GetType(BaseFixture))
End Function
End Class</pre>
<p>We’re calling log4net.Config,XmlConfiguration.Configure() just once. This loads the logging configuration from the app.config, which wires up log4net with Console.Out through the ConsoleAppender. With the example configuration, we'll get to see the SQL NHibernate is executing.</p>
<p>If you want something a lot more powerful, check out Ayende’s <a href="http://nhprof.com/" target="_blank">NHProf</a>.</p>
<h3>Problem #1</h3>
<pre>NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing. Type: NStackExample.Section, Entity: NStackExample.Section</pre>
<pre class="brush:vbnet"> Dim Course As New Course() With { _
.Subject = "SUBJ", _
.CourseNumber = "1234", _
.Title = "Title", _
.Description = "Description", _
.Hours = 3}
Dim Section As New Section() With { _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "1"}
Term.AddSection(Section)
Course.AddSection(Section)
Using Tran = Session.BeginTransaction()
ID = Session.Save(Course)
Session.Save(Section)
Tran.Commit() ' <==== Exception here
End Using
Session.Clear()</pre>
<p>When a transaction is committed, the session is flushed to the database. That just means data changes are written to the database. This exception is telling us we’re trying to save an object, but it references another object that isn’t saved. We can infer that this means cascading is turned off for this relationship. When we go to this particular line in the code, we see that this transaction is committing a save (INSERT) of a new course, and that this course references a new section. If this were a TestCascadeSaveFromParentToChild test, we would adjust our mapping. In this case, we’re testing the delete-orphan functionality, not the cascade of inserts and updates. We’ll explicitly save the section in this transaction as well.</p>
<p>After making the change and re-running our tests, we see that the same test is still failing, although it got further.</p>
<pre class="brush:vbnet"> 'Test removing
Course.RemoveSection(Section)
Using Tran = Session.BeginTransaction()
Session.Save(Course)
Tran.Commit() ' <==== Exception here
End Using
Session.Clear()</pre>
<p>Now we're violating a unique constraint. This is because we've called Session.Save(Course) twice. Session.Save is for saving new objects only. Session.SaveOrUpdate or simply Session.Update should be used to save the course. Since neither of those return the identifier, we'll need to get that from our initial Save. We make those change, recompile, and test.</p>
<p>Next, we get this:</p>
<pre>NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.Exceptions.GenericADOException : could not delete collection: [NStackExample.Course.Sections#912b489a-4d12-4bc9-9d68-9c6b0147b799][SQL: UPDATE "Section" SET Course_id = null WHERE Course_id = @p0]
----> System.Data.SQLite.SQLiteException : Abort due to constraint violation
Section.Course_id may not be NULL</pre>
<p>This message is telling us that when we disassociated the course from the section, NHibernate tried to set the Section's Course_id to NULL. This violated a not-null constraint. More importantly, this violated our business rule. The section was orphaned and should have been deleted. To corrected it, we update our mappings. In our course mapping, we’ll add Cascade.AllDeleteOrphan() to the one-to-many sections relationship.</p>
<pre class="brush:vbnet"> HasMany(Function(x As Course) x.Sections) _
.AsSet() _
.WithForeignKeyConstraintName("CourseSections") _
.Cascade.AllDeleteOrphan()</pre>
<p>After a compile and retest, we get this:</p>
<pre>NStackExample.Data.Tests.CourseMappingTests.CanCascadeOrphanDeleteFromCourseToSections:
NHibernate.PropertyValueException : not-null property references a null or transient valueNStackExample.Section.Course</pre>
<p>This error is strange. Basically, even though we’re going to delete the section now that it’s orphaned, NHibernate is complaining that we’ve set Section.Course = null / nothing. For now, simply to appease the marmot god, we’ll remove our not null constraint on Section.Course. If you turn on log4net NHibernate.SQL logging, you’ll see that this operation wouldn’t violate the NOT NULL database constraint. The orphaned row is being deleted. We’re only failing an internal NHibernate property check. I’m hoping for a better explanation from Tuna, one of the NHibernate gurus, who’s been extremely helpful with this series.</p>
<p>The second problem is basically a disconnect between relational database concepts and object relations. All one-to-many database relationships are bidirectional. The many-to-one is implied. In an object graph, we can have a reference from a parent to its children but not reference from the child back to the parent, or vice-versa. Object relationships are unidirectional. Even though it would indicate a bug in most circumstances, we still have to tell NHibernate which of our two unidirectional relationships is the “real” one that we want to persist to the database. The default is to use the one-to-many. This means that the relationship that is saved is based on membership in a course’s sections collection. We would rather have the relationship based on the many-to-one relationship: the Section’s Course property. To do this, we specify Inverse() in our mapping for Course.Sections. This tells NHibernate that the “other side” of the bidirectional relationship is the one we want to persist.</p>
<p>Bug solved. Onward! Wait. Compile it and rerun your tests. You may have unknowingly fixed other problems.</p>
<h3>Problem #2</h3>
<pre>NStackExample.Data.Tests.CourseMappingTests.CanCascadeSaveFromCourseToSections:
Expected: <nstackexample.section>
But was: <nstackexample.section></pre>
<p>This is another misleading issue. Our test is checking the equality of two sections.</p>
<p>Q: How did we define the equality of a section?</p>
<p>A: We didn’t, so Object.Equals is just looking to see if these two happen to be the same instance. Since one is rehydrated from the database, they aren’t. We’ll have to define our own equality check.</p>
<p>Q: How should we define equality?</p>
<p>A: If two instances represent the same section, they are equal.  Wait. Why are we just talking about sections? Let’s expand that to cover all entities.</p>
<p>Q: Where can we put this rule?</p>
<p>A: We should override Equals In our base Entity class, so all entities can use it.</p>
<p>Q: How do we know if two instances represent the same entity?</p>
<p>A: The ID fields will be equal.</p>
<p>Q: What about when we haven’t persisted the object and don’t have an ID yet?</p>
<p>A: We’ll assume they’re not equal. If a specific class needs something more accurate, it can override Equals again.</p>
<p>Here’s the code:</p>
<pre class="brush:vbnet"> Public Overrides Function Equals(ByVal obj As Object) As Boolean
Dim other As Entity = TryCast(obj, Entity)
If other Is Nothing Then Return False
Return ID.Equals(other.ID) AndAlso Not ID.Equals(Guid.Empty)
End Function</pre>
<p>Let’s recompile and test again. Look at that! We have 6 out of 10 tests passing now.</p>
<h3>Problem #3</h3>
<pre>NStackExample.Data.Tests.SectionMappingTests.CanCascadeSaveFromSectionToStudentSections:
NHibernate.PropertyValueException : not-null property references a null or transient valueNStackExample.Student.MiddleName</pre>
<p>This particular error can be fixed in two ways. We have defined our Student mapping to not allow null middle names. Our test of the Sections cascade is failing because it doesn’t set a value in middle name. We can either change our test to put something, even an empty string in middle name, or we can change our mapping to allow nulls. I choose option #1. Changing our mapping to allow nulls could lead to NullReferenceExceptions. Let’s set MiddleName = String.Empty around line 83. After a compile and test, we get this error.</p>
<pre>NStackExample.Data.Tests.SectionMappingTests.CanCascadeSaveFromSectionToStudentSections:
NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing. Type: NStackExample.StudentSection, Entity: NStackExample.StudentSection</pre>
<p>This error is saying that our cascade is failing. Why? Because we didn’t actually specify cascade on one of the one-to-many relationships pointing to  StudentSection. Since we know both Sections and Students should cascade to StudentSection, go add Cascade.All to both. Add Inverse() while you’re there.</p>
<p>Compile and retest. Success.</p>
<h3>Problem #4</h3>
<pre>NStackExample.Data.Tests.StudentMappingTests.CanCascadeSaveFromStudentToStudentSection:
NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing. Type: NStackExample.Student, Entity: NStackExample.Student</pre>
<p>This one is a bug in our test. If you look at what we're testing and what we're actually saving, you'll realize that we should be saving Student, not Section. Fix it and try again. Now we have the same MiddleName bug we had in problem #3. Fix it as well. Test again. Now we get a NullReferenceException. Why?</p>
<p>If you look at our test of the Student mapping, you’ll see that we’re not checking the correct results. This was most likely a sloppy cut-and-paste job in the middle of a conference call or some other distracting scenario. Swap in the correct expected results:</p>
<pre class="brush:vbnet"> 'Check the results
Using Tran = Session.BeginTransaction
Student = Session.Get(Of Student)(ID)
Assert.AreEqual(1, Student.StudentSections.Count)
Assert.AreEqual(Student.StudentSections(0), StudentSection)
Tran.Commit()
End Using</pre>
<p>It works!</p>
<h3>Problem #5</h3>
<pre>NStackExample.Data.Tests.TermMappingTests.CanCascadeSaveFromTermToSections:
NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing. Type: NStackExample.Section, Entity: NStackExample.Section</pre>
<p>This is the same as problem #3. Our cascade from term is not cascading the save down to the section. Go add Cascade,All()and Inverse() to Term.Sections.</p>
<h3>Problem #6</h3>
<pre>NStackExample.Data.Tests.TermMappingTests.CanSaveAndLoadTerm:
Expected: "Fall 2009"
But was: null</pre>
<p>In this test, we see that we were expecting a value in the Name property of Term, but we got null / nothing. Whenever you see this, you should first check your mapping. In this case, you'll quickly discover that we didn't map that property. Go map it. Next, you'll discover a bug in our tests. We're comparing the wrong date. EndDate should be compared with December 1st, 2009.</p>
<h3>It works! </h3>
<p>That really wasn’t so terrible. It probably took more effort to read this post than it did to correct those bugs.</p>
<p>Oh yeah, and get some source control.</p>
<p><strike>Before I post the source code, I’ll be updating to Fluent NHibernate v1.0 RC and fixing some of the typos and reference problems you’ve commented about. With any luck, the corrected source code for this part, along with the next part will be out before the weekend is over. </strike></p>
<p>Edit: Download the entire solution in <a href="http://jasondentler.com/downloads/NStackExample.Part5.VBNET.Zip" target="_blank">VB</a> or <a href="http://jasondentler.com/downloads/NStackExample.Part5.CSharp.Zip" target="_blank">C#</a>. I’ve upgraded to Fluent NHibernate v1 RC and updated most of the other assemblies.</p>
<p>Jason
<br />- Glad to be moving on to Ninject soon.</p>
Imagining the Tenth Dimension
2009-08-20T00:00:00+00:00
http://jasondentler.com/blog/2009/08/imagining-the-tenth-dimension
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:efcaf438-37cc-45fd-8778-679681342936" class="wlWriterEditableSmartContent"><div><embed type="application/x-shockwave-flash" src="http://flash.revver.com/player/1.0/player.swf" wmode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer" scale="noScale" salign="TL" bgcolor="#000000" flashvars="mediaId=99898&affiliateId=0&allowFullScreen=true" allowfullscreen="true" height="392" width="480"></embed></div></div> <p> </p> <p>The 5th post in the ASP.NET MVC / NHibernate series, <em>Fixing the Broken Stuff</em>,  will be out Friday night.</p>
Double many-to-one?
2009-08-20T00:00:00+00:00
http://jasondentler.com/blog/2009/08/double-many-to-one
<p>I’m working on a mapping for a project at work. The entity names have been changed to protect the innocent. </p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/ClassDiagram1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ClassDiagram1" border="0" alt="ClassDiagram1" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/ClassDiagram1_thumb.png" width="427" height="137" /></a> </p> <p>In the application I’m working on, the model is more like glasses with a left and right lens, but I’ve simplified it. </p> <pre class="brush:vbnet">Public Class Monocle
Inherits Entity
Private m_LeftLens As Lens
Public Overridable Property Lens() As Lens
Get
Return m_LeftLens
End Get
Set(ByVal value As Lens)
m_LeftLens = value
End Set
End Property
End Class
Public Class Lens
Inherits Entity
Private m_Glasses As Monocle
Public Overridable Property Monocle() As Monocle
Get
Return m_Glasses
End Get
Set(ByVal value As Monocle)
m_Glasses = value
End Set
End Property
End Class
Public Class MonocleMapping
Inherits ClassMap(Of Monocle)
Public Sub New()
Id(Function(x As Monocle) x.ID).GeneratedBy.GuidComb()
References(Function(x As Monocle) x.Lens) _
.Cascade.All() _
.WithForeignKey("MonocleLens")
End Sub
End Class
Public Class LensMapping
Inherits ClassMap(Of Lens)
Public Sub New()
Id(Function(x As Lens) x.ID).GeneratedBy.GuidComb()
References(Function(x As Lens) x.Monocle) _
.Cascade.All() _
.WithForeignKey("LensMonocle")
End Sub
End Class
<TestFixture()> _
Public Class GlassesMappingTests
<Test()> _
Public Sub CanCascadeSaveFromMonocleToLens()
Dim ID As Guid
Dim Monocle As Monocle
Dim Lens As Lens
Using Scope As New SQLiteDatabaseScope(Of MonocleMapping)
Using Session = Scope.OpenSession
Using Tran = Session.BeginTransaction
Monocle = New Monocle
Lens = New Lens With {.Monocle = Monocle}
Monocle.Lens = Lens
'These are just idiot checks...
Monocle.Should.Not.Be.Null()
Lens.Should.Not.Be.Null()
Monocle.Lens.Should.Be.SameInstanceAs(Lens)
Lens.Monocle.Should.Be.SameInstanceAs(Monocle)
ID = Session.Save(Monocle)
Tran.Commit()
End Using
End Using
Using Session = Scope.OpenSession
Using Tran = Session.BeginTransaction
Monocle = Session.Get(Of Monocle)(ID)
Monocle.Should.Not.Be.Null()
Monocle.ID.Should.Be.EqualTo(ID)
Monocle.Lens.Should.Not.Be.Null()
Monocle.Lens.Should.Not.Be.SameInstanceAs(Lens)
Monocle.Lens.Should.Be.EqualTo(Lens)
Monocle.Lens.Monocle.Should.Be.SameInstanceAs(Monocle)
Tran.Commit()
End Using
End Using
End Using
End Sub
End Class</pre>
<pre class="brush:csharp">
using NUnit.Framework;
using FluentNHibernate.Mapping;
public class Monocle : Entity
{
private Lens m_Lens;
public virtual Lens Lens {
get { return m_Lens; }
set { m_Lens = value; }
}
}
public class Lens : Entity
{
private Monocle m_Glasses;
public virtual Monocle Monocle {
get { return m_Glasses; }
set { m_Glasses = value; }
}
}
public class MonocleMapping : ClassMap<Monocle>
{
public MonocleMapping()
{
Id((Monocle x) => x.ID).GeneratedBy.GuidComb();
References((Monocle x) => x.Lens).Cascade.All().WithForeignKey("MonocleLens");
}
}
public class LensMapping : ClassMap<Lens>
{
public LensMapping()
{
Id((Lens x) => x.ID).GeneratedBy.GuidComb();
References((Lens x) => x.Monocle).Cascade.All().WithForeignKey("LensMonocle");
}
}
[TestFixture()]
public class GlassesMappingTests
{
[Test()]
public void CanCascadeSaveFromGlassesToLense()
{
Guid ID;
Monocle Monocle;
Lens Lens;
using (SQLiteDatabaseScope<MonocleMapping> Scope = new SQLiteDatabaseScope<MonocleMapping>()) {
using (Session == Scope.OpenSession()) {
using (Tran == Session.BeginTransaction()) {
Monocle = new Monocle();
Lens = new Lens { Monocle = Monocle };
Monocle.Lens = Lens;
//These are just idiot checks...
Monocle.Should.Not.Be.Null();
Lens.Should.Not.Be.Null();
Monocle.Lens.Should.Be.SameInstanceAs(Lens);
Lens.Monocle.Should.Be.SameInstanceAs(Monocle);
ID = Session.Save(Monocle);
Tran.Commit();
}
}
using (Session == Scope.OpenSession) {
using (Tran == Session.BeginTransaction) {
Monocle = Session.Get<Monocle>(ID);
Monocle.Should.Not.Be.Null();
Monocle.ID.Should.Be.EqualTo(ID);
Monocle.Lens.Should.Not.Be.Null();
Monocle.Lens.Should.Not.Be.SameInstanceAs(Lens);
Monocle.Lens.Should.Be.EqualTo(Lens);
Monocle.Lens.Monocle.Should.Be.SameInstanceAs(Monocle);
Tran.Commit();
}
}
}
}
}
</pre>
<p>Here’s the resulting SQL.</p>
<pre>drop table if exists "Monocle"
drop table if exists "Lens"
create table "Monocle" (ID UNIQUEIDENTIFIER not null, Lens_id UNIQUEIDENTIFIER, primary key (ID))
create table "Lens" (ID UNIQUEIDENTIFIER not null, Monocle_id UNIQUEIDENTIFIER, primary key (ID))
INSERT INTO "Lens" (Monocle_id, ID) VALUES (@p0, @p1); @p0 = '', @p1 = 'f6f37089-a66b-4007-b732-9c6b008d1448'
INSERT INTO "Monocle" (Lens_id, ID) VALUES (@p0, @p1); @p0 = 'f6f37089-a66b-4007-b732-9c6b008d1448', @p1 = 'bb2879f6-d27a-4eb0-8bf0-9c6b008d143b'
UPDATE "Lens" SET Monocle_id = @p0 WHERE ID = @p1; @p0 = 'bb2879f6-d27a-4eb0-8bf0-9c6b008d143b', @p1 = 'f6f37089-a66b-4007-b732-9c6b008d1448'
SELECT monocle0_.ID as ID0_0_, monocle0_.Lens_id as Lens2_0_0_ FROM "Monocle" monocle0_ WHERE monocle0_.ID=@p0; @p0 = 'bb2879f6-d27a-4eb0-8bf0-9c6b008d143b'
SELECT lens0_.ID as ID1_0_, lens0_.Monocle_id as Monocle2_1_0_ FROM "Lens" lens0_ WHERE lens0_.ID=@p0; @p0 = 'f6f37089-a66b-4007-b732-9c6b008d1448'</pre>
<p>Of course, I think that making this a double many-to-one relationship is probably wrong, but it gets me close to a working solution. </p>
<p>This works, except for the unnecessary UPDATE “Lens” statement. In my mind, since I’m using the GuidComb generator, NHibernate should specify the Monicle_id in the INSERT “Lens” statement. Instead, it’s inserting NULL, then updating it later. This prevents me from putting a NOT NULL constraint on Lens.Monicle_id. It’s been suggested that I have superfluous update, and I agree. However, the prescribed inverse=”true” won’t work. I don’t have a one-to-many relationship to put it on.</p>
<p>I’ve tried using HasOne instead of References to create a bidirectional one-to-one relationship. It didn’t work at all. My database schema didn’t even have FK fields. </p>
<p>Am I missing something or is this double many-to-one as good as it’s going to get?</p>
Polka is the new rock
2009-08-17T00:00:00+00:00
http://jasondentler.com/blog/2009/08/polka-is-the-new-rock
<p>Or so says Windows Media Player. This made me laugh.</p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb8.png" width="243" height="132" /></a> </p> <p>Polkastra’s new album, Apolkalypse Now, with special guest William Barton on Didgeridoo.</p>
LivingRoom.NET
2009-08-17T00:00:00+00:00
http://jasondentler.com/blog/2009/08/livingroom-net
<p>Today, a coworker asked me about my living room setup. I figured it would be a nice change from the <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> / <a href="http://nhforge.org" target="_blank">NHibernate</a> series. It’s a little unorganized and rushed. I apologize.</p> <p>I hate remotes. There is absolutely no reason to have more than one remote control. I also hate looking at wires and equipment with blinking lights in my living room.</p> <p>Here’s what I did to fix the problem.</p> <h3>Layout</h3> <p>Just on the other side of the wall from my LCD TV is a large walk-in closet.</p> <p>In the living room, in addition to my Sharp Aquos LCD TV, I also have Energy brand 5.1 surround speakers and a <a href="http://www.logitechsqueezebox.com/" target="_blank">Logitech Squeezebox</a> (now referred to as Squeezebox Classic) network music device.  In the closet, I have my laptop, external SATA hard drive, Onkyo TX-SR706 receiver, and AT&T U-Verse set top box.</p> <h3>Electrical</h3> <p>If you don’t know what you’re doing, you could burn down your house, die or worse. Hire a professional. Also, if you live inside city limits, there’s probably some law or ordinance about having the work done or inspected by a licensed electrician.</p> <p>Problem #1 – The walk in closet didn’t have any electrical outlets. Luckily, there’s one in the living room on the same wall. I ran a few feet of spare 12 gauge home electrical wire from the outlet in the living room to a new outlet in the closet. Be sure you know which side of the wall stud the outlet is on. You can’t easily run wire through a wall stud without destroying your drywall.</p> <p>So, I added an outlet in the closet. Problem solved.</p> <p>Problem #2 - Your standard home electronics power cord is not rated for in-wall use, or at least that’s what I read on the internet. I didn’t want a power cord hanging from my TV running down to an outlet. I needed to add an electrical outlet behind my LCD TV, which was mounted on the wall. I also wanted some sort of surge protection.</p> <p>I went shopping online for something that would solve this problem and ran across <a href="http://www.monoprice.com/products/product.asp?c_id=105&cp_id=10425&cs_id=1042505&p_id=4006&seq=1&format=1#largeimage" target="_blank">this recessed low voltage wall plate with recessed power</a> at Monoprice.com.</p> <p><img style="display: inline; margin-left: 0px; margin-right: 0px" alt="Large Product Image for Recessed Low Voltage Cable Wall Plate WITH Recessed Power - White" align="right" src="http://images.monoprice.com/productlargeimages/40061.jpg" width="240" height="181" /></p> <p>It’s actually a kit designed specifically for this problem. There are two wall plates included in the package. The one shown in the picture goes behind the LCD. It has a single electrical outlet plus a channel for low-voltage cables, such as speaker and HDMI cables. The other wall plate goes in the closet and is identical except the channel feeds down and the outlet is male. You provide two single electrical junction boxes – one for each of the electrical outlets. Between the two, use standard in-wall rated 12 gauge electrical wire.</p> <p>This is not directly wired in to the home’s electrical. The two wall boxes are wired to each other only. You connect the male outlet to a surge protector, which is plugged in to a standard electrical outlet. Then, just plug your LCD in to the female side. You have powered your LCD, protected it from surges and lightning strikes, hidden the power cable behind the TV, and made a path through the wall for your low-voltage cables.</p> <h3>Pulling cable<a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0309.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="DSCF0309" border="0" alt="DSCF0309" align="right" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0309_thumb.jpg" width="184" height="244" /></a></h3> <p>I had help with this part. My little brother ran the speaker wires through the attic and down the walls while I pulled from below and connected everything.</p> <p>We ran 14 gauge speaker wire to the surround speakers and the subwoofer. Since the subwoofer is powered, it uses an RCA cable. I soldered a male RCA connector to each end of the subwoofer speaker cable. For the speakers, I used standard banana plug speaker wall plates.</p> <p>We also pulled some coax cable in to the closet and connected it in the attic to the rest of the cable TV lines with a splitter. .</p> <p>The left, right, and center speaker cables run through the low-voltage side of the wall plate behind the TV.</p> <h3>Wall-mounting</h3> <p>I found some cheap plastic speaker mounts on sale at Best Buy. You get what you pay for. The package said they were rated for up to 25 pounds. I seriously doubt these things could support that kind of weight, but they worked for my surround and left/right speakers. The center speaker is a little heavier, so it just sits on a shelf below the TV.</p> <p>For the TV, I bought a generic LCD TV wall mount at Fry’s electronics. It doesn’t tilt or pivot or any of that mess. It just holds the TV on to the wall, which is just fine with me.</p> <h3>Hardware</h3> <p>The laptop and the U-Verse set top box are connected to the receiver with HDMI cables. The Squeezebox is audio only and is connected with a single digital RCA cable. The receiver is also connected to the TV with an HDMI cable.</p> <p>Both the TV and the receiver have RS232 9-pin serial management ports you can use to control the devices. The receiver also allows you to query its state – is it turned on, what’s the volume set at, what input is active, etc.</p> <p><strong>Just a note</strong>: You will need a null modem cable when connecting to a Sharp Aquos TV and a standard straight through serial cable when connecting to Onkyo brand equipment. Also, there is at least one person in the hardware department at the Webster, TX Fry’s Electronics who still knows what a null modem cable is. That is not the case with any of the area Best Buy or Radio Shack stores. <a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF03061.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="DSCF0306" border="0" alt="DSCF0306" align="right" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0306_thumb.jpg" width="244" height="184" /></a></p> <p>Since like most modern PCs, my laptop didn’t have any serial ports, I bought some USB serial ports from Amazon. Be sure to read the fine print and the comments. Most of these don’t come with drivers for Vista at all. I only found one that would work with Vista x64, and the install was a little hackish.</p> <p>The only way to control the U-Verse box is with an infrared remote. It doesn’t have a serial port, the USB port is disabled, and even though it’s running WinCE, I couldn’t find a way in through the network.</p> <p>I bought a <a href="http://www.usbuirt.com/" target="_blank">USB UIRT</a> and some stick-on infrared blasters off the internet to control it. There are all sorts of internet posts explaining where the IR receiver is located inside the U-Verse box. This is what worked for me.</p> <p>That’s almost all of the hardware. I also have an RF keyboard, RF optical mouse, and an iPod touch that I use as my one and only remote control.</p> <h3>Software</h3> <p>All of the software is written in Visual Basic.NET with ASP.NET MVC and iUI, a javascript library for making web applications look and behave like native iPhone apps.</p> <p>All of the device control is done with macros and commands stored in an XML file. For example, each button on the U-Verse remote is mapped to an array of 32-bit integers stored as hex strings. These hex strings represent the actual IR commands that are sent to the USB UIRT to control the U-Verse box.</p> <p>TV guide information is downloaded once a week from the internet using XMLTV and stored in a SQL Server database on the laptop.</p> <p>Here are some pictures of the front-end on the iPod touch and the setup in general.</p> <p> </p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0315.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0315" border="0" alt="DSCF0315" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0315_thumb.jpg" width="184" height="244" /></a><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0316.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0316" border="0" alt="DSCF0316" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0316_thumb.jpg" width="184" height="244" /></a><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0317.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0317" border="0" alt="DSCF0317" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0317_thumb.jpg" width="184" height="244" /></a> <a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0319.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0319" border="0" alt="DSCF0319" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0319_thumb.jpg" width="184" height="244" /></a> <a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0318.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0318" border="0" alt="DSCF0318" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0318_thumb.jpg" width="184" height="244" /></a> <a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0312.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DSCF0312" border="0" alt="DSCF0312" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/DSCF0312_thumb.jpg" width="244" height="184" /></a></p> Send me an email if you would like a copy of the xml file with the UVerse remote codes.
How-To: Using the N* Stack, part 4
2009-08-15T00:00:00+00:00
http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-4
<p>This is part 4 of my series on <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> and NHibernate. If you’re not up to date, you can go check out:</p> <ul> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">Part 1</a> – Setting up the Visual Studio solution </li> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">Part 2</a> – Building the model </li> <li><a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/" target="_blank">Part 3</a> – Mapping the model to the database </li> </ul> <p>As promised, today, we’re going to test our mappings and get a little familiar with using <a href="http://nhforge.org" target="_blank">NHibernate</a>.</p> <p>We’ll be using NUnit 2.5.2, but any recent version should work.</p> <p><strong>Disclaimer</strong>: I’m still learning some of this myself, so use at your own risk. This may not be considered best practice. Also, there’s almost certainly better ways to write these tests using one of the dozens of popular testing frameworks out there, but we’re using plain vanilla NUnit.</p> <p>Let’s create a new Class Library project for our tests. We’ll call it NStackExample.Data.Tests. Now, in the data test project, add references to your core project, data project, NHibernate.dll, FluentNHibernate.dll, and NUnit.Framework.dll. If you’ve installed NUnit, NUnit.Framework.dll will be on the .NET tab. If you have multiple versions of NUnit installed, be sure to pick the right version.</p> <h3>SQL: Now in a convenient travel size</h3> <p>If you haven’t heard of SQLite before, you’re going to love this. It’s a tiny, self-contained, open-source SQL database engine in a DLL. Even better, it can run entirely in-memory and it’s blazing fast. Here’s how you get set up to use it:</p> <ol> <li>Download the SQLite ADO.NET Provider from here. Get the full version – the one named something like SQLLit-1.0.65.0-setup.exe. Install it, then grab a copy of System.Data.Sqlite.dll and put it in your Solution Items folder with all the other 3rd party libraries. If you’re running on a 64-bit operating system, grab the one from the binx64 directory. If not, use the one in bin. </li> <li>Download the SQLite library itself. Scroll down to Precompiled Binaries for Windows. It should be named something like sqlitedll-3_6_17.zip. Extract the SQLite3.dll to your Solution Items folder. </li> <li>In your data test project, add a reference to System.Data.SQLite.dll. </li> <li>Because SQLite3.dll was written in C and is completely unmanaged, we can’t add a direct reference to it. To ensure it gets put in the right place, we’re going to set it up as a content file. Right click on your data test project, choose Add Existing Item, then browse for SQLite3.dll. Add it. In Solution Explorer, it’ll be mixed in with the code for your project. Right click on it and choose properties. Set it to Copy Always. This will copy it to the binDebug or binRelease folder every time your project is built, so it never gets forgotten. </li> <li>If you haven’t already, grab the code for the SQLiteDatabaseScope class from <a href="http://jasondentler.com/blog/2009/08/nhibernate-unit-testing-with-sqlite-in-memory-db/" target="_blank">my previous post</a>. Add it to your data test project. </li> </ol> <h3>A simple mapping test</h3> <pre class="brush:vbnet">Imports NUnit.Framework
<TestFixture()> _
Public Class CourseMappingTests
<Test()> _
Public Sub CanLoadAndSaveCourse()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using Session = Scope.OpenSession
Dim ID As Guid
Dim Course As Course
Using Tran = Session.BeginTransaction
ID = Session.Save(New Course With { _
.Subject = "SUBJ", _
.CourseNumber = "1234", _
.Title = "Title", _
.Description = "Description", _
.Hours = 3})
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
Course = Session.Get(Of Course)(ID)
Assert.AreEqual("SUBJ", Course.Subject)
Assert.AreEqual("1234", Course.CourseNumber)
Assert.AreEqual("Title", Course.Title)
Assert.AreEqual("Description", Course.Description)
Assert.AreEqual(3, Course.Hours)
Tran.Commit()
End Using
End Using
End Using
End Sub
End Class</pre>
<pre class="brush:csharp">using System;
using NUnit.Framework;
using NHibernate;
namespace NStackExample.Data.Tests
{
[TestFixture]
public class CourseMappingTests
{
[Test]
public void CanSaveAndLoadCourse()
{
using (SQLiteDatabaseScope<CourseMapping> Scope = new SQLiteDatabaseScope<CourseMapping>())
{
using (ISession Session = Scope.OpenSession())
{
Guid ID;
Course Course;
using (ITransaction Tran = Session.BeginTransaction())
{
ID = (Guid)Session.Save(new Course
{
Subject = "SUBJ",
CourseNumber = "1234",
Title = "Title",
Description = "Description",
Hours = 3
});
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction())
{
Course = Session.Get<Course>(ID);
Assert.AreEqual("SUBJ", Course.Subject);
Assert.AreEqual("1234", Course.CourseNumber);
Assert.AreEqual("Title", Course.Title);
Assert.AreEqual("Description", Course.Description);
Assert.AreEqual(3, Course.Hours);
Tran.Commit();
}
}
}
}
}
}</pre>
<p>Here’s how it works:</p>
<ul>
<li>First, we get a fresh in-memory SQLite database with our schema built. </li>
<li>Put a new course in the database </li>
<li>Clear the session </li>
<li>Get the course back out of the database </li>
<li>Check to make sure each of our properties survived the trip. If they didn’t, fail the test. </li>
</ul>
<p>There’s a few things that may be new to you.</p>
<ul>
<li>Our class has the TestFixture attribute. This tells NUnit that this class contains tests. </li>
<li>Each subroutine has the Test attribute. This tells NUnit that this method is a test. </li>
<li>The SQLiteDatabaseScope is almost certainly new, considering I wrote it Friday. You can read my previous post for more information. </li>
</ul>
<h3>Use of implicit transaction is discouraged</h3>
<p>You’re probably wondering why I would wrap such simple one-statement database logic in a transaction, especially a Session.Get, which is essentially a single select statement. Prior to writing this series, I wouldn’t have done it that way. Rookie mistake.</p>
<p>While doing research for this entry, I ran across <a href="http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx" target="_blank">an example test</a> from Ayende. He was using transactions on everything,  even his calls to Session.Get. I asked him why and he sent me a link to this <a href="http://nhprof.com/Learn/Alert?name=DoNotUseImplicitTransactionsHibernate" target="_blank">NHProfiler Alert</a>. It’s important and not obvious – at least not to me - so with permission, I’ve quoted the entire page.</p>
<blockquote>
<p>A common mistake when using a database is to use transactions only when orchestrating several write statements. In reality, every operation that the database is doing is done inside a transaction, including queries and writes (update, insert, delete).</p>
<p>When we don't define our own transactions, it falls back into implicit transaction mode, where every statement to the database runs in its own transaction, resulting in a large performance cost (database time to build and tear down transactions), and reduced consistency.</p>
<p>Even if we are only reading data, we should use a transaction, because using transactions ensures that we get consistent results from the database. Hibernate assumes that all access to the database is done under a transaction, and strongly discourages any use of the session without a transaction.</p>
<pre class="brush:csharp">Session session = sessionFactory.openSession();
try {
Transaction tx = session.beginTransaction();
try {
//execute code that uses the session
} finally {
tx.commit();
}
} finally {
session.close();
}</pre>
<p>Leaving aside the safety issue of working with transactions, the assumption that transactions are costly and that we need to optimize them is false. As previously mentioned, databases are always running in a transaction. Also, they have been heavily optimized to work with transactions.</p>
<p>The real question here is: Is the transaction per-statement or per-batch? There is a non-trivial amount of work that needs to be done to create and dispose of a transaction; having to do it per-statement is more costly than doing it per-batch.</p>
<p>It is possible to control the number and type of locks that a transaction takes by changing the transaction isolation level (and, indeed, a common optimization is to reduce the isolation level).</p>
<p>Hibernate treats the call to commit() as the time to flush all changed items from the unit of work to the database, and without an explicit call to Commit(), it has no way of knowing when it should do that. A call to Flush() is possible, but it is frowned upon because this is usually a sign of improper transaction usage.</p>
<p>I strongly suggest that you use code similar to that shown above (or use another approach to transactions, such as TransactionScope, or Castle's Automatic Transaction Management) in order to handle transactions correctly.</p>
<h5>Transaction and the second level cache</h5>
<p>Another implication of not using explicit transactions with Hibernate is related to the use of the second level cache.</p>
<p>Hibernate goes to great length in order to ensure that the 2nd level cache maintains a consistent view of the database. This is accomplished by deferring all 2nd level cache updates to the transaction commit. In this way, we can assert that the data in the 2nd level cache is the one committed to the database.</p>
<p>Forgoing the use of explicit transactions has the effect of nulling the 2nd level cache. Here is an example that would make this clear:</p>
<pre class="brush:csharp">try {
Post post = session.get(Post.class, 1);
// do something with post
} finally {
session.close();
}</pre>
<p>Even if the 2nd level cache is enabled for Post, it is still not going to be cached in the 2nd level cache. The reason is that until we commit a transaction, Hibernate will not update the cache with the values for the loaded entities.</p>
<p>This code, however, does make use of the 2nd level cache:</p>
<pre class="brush:csharp">Session session = sessionFactory.openSession();
try {
Transaction tx = sessionFactory.beginTransaction();
try {
Post post = session.get(Post.class, 1);
// do something with post
} finally {
tx.commit();
}
} finally {
session.close();
}</pre>
</blockquote>
<p> </p>
<h3>A slightly more complicated mapping test</h3>
<p>When an entity has a required parent, as in the case of our section, you must create and insert the parent before actually testing the child. We’re not testing the cascade here. That’s a separate test. In this case, section has two required parents: a course, and a term. Here’s the test:</p>
<pre class="brush:vbnet"> <Test()> _
Public Sub CanLoadAndSaveCourse()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using Session = Scope.OpenSession
Dim ID As Guid
Dim Section As Section
Dim Course As New Course With { _
.Subject = "SUBJ", _
.CourseNumber = "1234", _
.Title = "Title", _
.Description = "Description", _
.Hours = 3}
Dim Term As New Term With { _
.Name = "Fall 2009", _
.StartDate = New Date(2009, 9, 1), _
.EndDate = New Date(2009, 12, 1)}
'We're not testing the cascade, so save the parents first...
Using Tran = Session.BeginTransaction
Session.Save(Course)
Session.Save(Term)
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
ID = Session.Save(New Section With { _
.Course = Course, _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "1W", _
.Term = Term})
Tran.Commit()
End Using
Session.Clear()
Using Tran = Session.BeginTransaction
Section = Session.Get(Of Section)(ID)
Assert.AreEqual(Course, Section.Course)
Assert.AreEqual("FacultyName", Section.FacultyName)
Assert.AreEqual("R1", Section.RoomNumber)
Assert.AreEqual("1W", Section.SectionNumber)
Assert.AreEqual(Term, Section.Term)
Tran.Commit()
End Using
End Using
End Using
End Sub</pre>
<pre class="brush:csharp"> [Test]
public void CanSaveAndLoadSection()
{
using (SQLiteDatabaseScope<CourseMapping> Scope = new SQLiteDatabaseScope<CourseMapping>) {
using (ISession Session = Scope.OpenSession()) {
Guid ID;
Section Section;
Course Course = new Course {
Subject = "SUBJ",
CourseNumber = "1234",
Title = "Title",
Description = "Description",
Hours = 3};
Term Term = new Term {
Name = "Fall 2009",
StartDate = new DateTime(2009,8,1),
EndDate = new DateTime(2009,12,1)};
// We're not testing the cascade here, so explicitly save these parent objects.
using (ITransaction Tran = Session.BeginTransaction()) {
Session.Save(Course);
Session.Save(Term);
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction()) {
ID = (Guid) Session.Save(new Section {
Course = Course,
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "W1",
Term = Term});
Tran.Commit();
}
Session.Clear();
using (ITransaction Tran = Session.BeginTransaction()) {
Section = Session.Get<Section>(ID);
Assert.AreEqual(Course, Section.Course);
Assert.AreEqual("FacultyName", Section.FacultyName);
Assert.AreEqual("R1",Section.RoomNumber);
Assert.AreEqual("W1", Section.SectionNumber);
Assert.AreEqual(Term, Section.Term);
Tran.Commit();
}
}
}
}</pre>
<h3>Testing the cascade</h3>
<p>“Cascade what? “</p>
<p>In your application, when you’ve just registered a student for a whole bunch of classes, usually with several changes along the way, you don’t want to have to remember what entities were added, removed or changed. That’s just crazy. Thanks to the Cascade functionality in NHibernate, you don’t have to do that. Just save the student entity. If your mappings are correct, it just works™.</p>
<p>For some people, especially me, that’s a big if. That’s why we test our mappings.</p>
<pre class="brush:vbnet"> <Test()> _
Public Sub CanCascadeSaveFromCourseToSections()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using Session = Scope.OpenSession
Dim ID As Guid
Dim Term As New Term With { _
.Name = "Fall 2009", _
.StartDate = New Date(2009, 9, 1), _
.EndDate = New Date(2009, 12, 1)}
'We're not testing the cascade of section -> term here
Using Tran = Session.BeginTransaction
Session.Save(Term)
Tran.Commit()
End Using
Session.Clear()
Dim Course As New Course With { _
.Subject = "SUBJ", _
.CourseNumber = "1234", _
.Title = "Title", _
.Description = "Description", _
.Hours = 3}
Dim Section1 As New Section With { _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "1", _
.Term = Term}
Dim Section2 As New Section With { _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "2", _
.Term = Term}
Course.AddSection(Section1)
Course.AddSection(Section2)
'Test saving
Using Tran = Session.BeginTransaction
ID = Session.Save(Course)
Tran.Commit()
End Using
Session.Clear()
'Check the results
Using Tran = Session.BeginTransaction
Course = Session.Get(Of Course)(ID)
Assert.AreEqual(2, Course.Sections.Count)
Assert.AreEqual(1, Course.Sections _
.Where(Function(S As Section) _
S.Equals(Section1)) _
.Count(), "Course.Sections does not contain section 1.")
Assert.AreEqual(1, Course.Sections _
.Where(Function(S As Section) _
S.Equals(Section2)) _
.Count(), "Course.Sections does not contain section 2.")
Tran.Commit()
End Using
End Using
End Using
End Sub</pre>
<pre class="brush:csharp"> [Test()]
public void CanCascadeSaveFromCourseToSections()
{
using (SQLiteDatabaseScope<coursemapping> Scope = new SQLiteDatabaseScope<coursemapping>())
{
using (ISession Session = Scope.OpenSession())
{
Guid ID;
Term Term = new Term {
Name = "Fall 2009",
StartDate = new System.DateTime(2009, 9, 1),
EndDate = new System.DateTime(2009, 12, 1) };
//We're not testing the cascade of section -> term here
using (ITransaction Tran = Session.BeginTransaction())
{
Session.Save(Term);
Tran.Commit();
}
Session.Clear();
Course Course = new Course {
Subject = "SUBJ",
CourseNumber = "1234",
Title = "Title",
Description = "Description",
Hours = 3 };
Section Section1 = new Section {
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "1",
Term = Term };
Section Section2 = new Section {
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "2",
Term = Term };
Course.AddSection(Section1);
Course.AddSection(Section2);
//Test saving
using (ITransaction Tran = Session.BeginTransaction())
{
ID = (Guid) Session.Save(Course);
Tran.Commit();
}
Session.Clear();
//Check the results
using (ITransaction Tran = Session.BeginTransaction())
{
Course = Session.Get<course>(ID);
Assert.AreEqual(2, Course.Sections.Count);
Assert.AreEqual(1, Course.Sections
.Where(S => S.Equals(Section1)).Count(),
"Course.Sections does not contain section 1.");
Assert.AreEqual(1, Course.Sections
.Where(S => S.Equals(Section2)).Count(),
"Course.Sections does not contain section 2.");
Tran.Commit();
}
}
}
}</pre>
<p>The test above will make sure new and/or updated sections are saved when you save the course. Here’s how it works:</p>
<ul>
<li>Get a fresh SQLite DB </li>
<li>Since we’re not testing terms, but we need one for our sections, build a term and stick it in the database. </li>
<li>Build a course and two sections. </li>
<li>Save the course </li>
<li>Clear the session </li>
<li>Get the course </li>
<li>Make sure it has our two sections </li>
</ul>
<p>What should happen when you remove a section from a course? A parent course is required for each section. Remember, we specified not nullable in the mapping. More importantly, an orphaned section isn’t allowed in the real world. So, if a section is orphaned, it should be deleted. We need to write a test for that.</p>
<pre class="brush:vbnet"> <Test()> _
Public Sub CanCascadeOrphanDeleteFromCourseToSections()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using Session = Scope.OpenSession
Dim ID As Guid
Dim Term As New Term With { _
.Name = "Fall 2009", _
.StartDate = New Date(2009, 9, 1), _
.EndDate = New Date(2009, 12, 1)}
Using Tran = Session.BeginTransaction
'We're not testing the cascade of section -> term here
Session.Save(Term)
Tran.Commit()
End Using
Session.Clear()
Dim Course As New Course With { _
.Subject = "SUBJ", _
.CourseNumber = "1234", _
.Title = "Title", _
.Description = "Description", _
.Hours = 3}
Dim Section1 As New Section With { _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "1", _
.Term = Term}
Dim Section2 As New Section With { _
.FacultyName = "FacultyName", _
.RoomNumber = "R1", _
.SectionNumber = "2", _
.Term = Term}
Course.AddSection(Section1)
Course.AddSection(Section2)
Using Tran = Session.BeginTransaction
Session.Save(Course)
Tran.Commit()
End Using
Session.Clear()
'Test removing
Course.RemoveSection(Section1)
Using Tran = Session.BeginTransaction
ID = Session.Save(Course)
Tran.Commit()
End Using
Session.Clear()
'Check the results
Using Tran = Session.BeginTransaction
Course = Session.Get(Of Course)(ID)
Assert.AreEqual(1, Course.Sections.Count())
Assert.AreEqual(0, Course.Sections _
.Where(Function(S As Section) _
S.Equals(Section1)) _
.Count(), "Course.Sections still contains section 1")
Tran.Commit()
End Using
End Using
End Using
End Sub</pre>
<pre class="brush:csharp"> [Test()]
public void CanCascadeOrphanDeleteFromCourseToSections()
{
using (SQLiteDatabaseScope<CourseMapping> Scope = new SQLiteDatabaseScope<CourseMapping>())
{
using (ISession Session = Scope.OpenSession())
{
Guid ID;
Term Term = new Term {
Name = "Fall 2009",
StartDate = new System.DateTime(2009, 9, 1),
EndDate = new System.DateTime(2009, 12, 1) };
using (ITransaction Tran = Session.BeginTransaction())
{
//We're not testing the cascade of section -> term here
Session.Save(Term);
Tran.Commit();
}
Session.Clear();
Course Course = new Course {
Subject = "SUBJ",
CourseNumber = "1234",
Title = "Title",
Description = "Description",
Hours = 3 };
Section Section1 = new Section {
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "1",
Term = Term };
Section Section2 = new Section {
FacultyName = "FacultyName",
RoomNumber = "R1",
SectionNumber = "2",
Term = Term };
Course.AddSection(Section1);
Course.AddSection(Section2);
using (ITransaction Tran = Session.BeginTransaction())
{
Session.Save(Course);
Tran.Commit();
}
Session.Clear();
//Test removing
Course.RemoveSection(Section1);
using (ITransaction Tran = Session.BeginTransaction())
{
ID = (Guid) Session.Save(Course);
Tran.Commit();
}
Session.Clear();
//Check the results
using (ITransaction Tran = Session.BeginTransaction())
{
Course = Session.Get<Course>(ID);
Assert.AreEqual(1, Course.Sections.Count());
Assert.AreEqual(0, Course.Sections
.Where(S => S.Equals(Section1)).Count(),
"Course.Sections still contains section 1");
Tran.Commit();
}
}
}
}</pre>
<p>I hope you see where I’m going with this one. Except for query tests, which we’ll do when we write our DAOs, that’s it for NHibernate testing. We do the same types of tests for our other entity classes.</p>
<h3>But…</h3>
<p>So, I bet you’re thinking “This mess won’t compile and even if it did, almost all of your tests would fail!” Yep. If the tests always pass, why write them?</p>
<p>Normally, I’d at least declare those missing functions so the solution would compile, but in this case, the discussion of those issues fits better with our next topic: How do we fix the broken stuff?</p>
<p><strike>Download links for the complete solution in both languages are coming soon.</strike></p>
<p>Edit: Download VB.NET <a href="http://jasondentler.com/downloads/NStackExample.Part4.VBNET.zip" target="_blank">here</a> or C# <a href="http://jasondentler.com/downloads/NStackExample.Part4.CSharp.zip" target="_blank">here</a>. To simplify things, I’ve removed the StudentTerm entity from the model.</p>
<p>Jason
<br />
<br />- Testy and in need of sleep.</p>
<p>References: <a href="http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx" target="_blank">Ayende’s blog post</a>, <a href="http://devlicio.us/blogs/krzysztof_kozmic/archive/2009/08/14/testing-with-nhibernate-and-sqlite.aspx" target="_blank">Krzysztof Kozmic’s recent post on Devlio.us</a>, <a href="http://www.tigraine.at/2009/05/29/fluent-nhibernate-gotchas-when-testing-with-an-in-memory-database/" target="_blank">Daniel Hoebling’s blog post</a>, <a href="http://nhprof.com/Learn/UserGuide" target="_blank">Ayende’s NHProfiler Alerts</a>.</p>
Poor man's NUnit + Visual Studio integration
2009-08-14T00:00:00+00:00
http://jasondentler.com/blog/2009/08/poor-mans-nunit-visual-studio-integration
<p>In part 4 of the series on <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> and <a href="http://nhforge.org" target="_blank">NHibernate</a>, we’ll be using NUnit. If you don’t already have some snazzy Visual Studio add-in with full NUnit integration, here’s a not-so-glitzy alternative. It’s not my idea and I’d love to give credit to the right person, but I’ve slept a lot since I first discovered this.</p> <p> </p> <ol> <li>In Visual Studio, on the Tools, choose External Tools.</li> <li>Click Add</li> <li>Title it NUnit or something similar.</li> <li>For the command, browse for the NUnit executable. In my case, it’s in C:Program Files (x86)NUnit 2.5.2binnet-2.0</li> <li>For the arguments, enter this: $(ProjectDir)binDebug$(TargetName)$(TargetExt) /run</li> <li>For the initial directory, enter this:$(ProjectDir)binDebug</li> </ol> <p>It should look something like this:</p> <p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb7.png" width="475" height="462" /></a></p> <p> </p> <p>Now, when you want to fire up NUnit, just choose it from the Tools menu. It’ll launch, load up the latest debug build of the current project, and start running the tests.</p> <p>Of course, if you’re doing any kind of significant real-world project, especially with a team, you should really look in to snagging one of the awesome continuous integration (CI) setups out there. Every time you commit, it’ll build and test your app, send you the results, and with a little tweaking, even start a fresh pot of coffee. Oh. You are using some kind of source control, right? And it’s not Visual Source Safe, right?</p> <p>Jason <br />- On a blogging high</p>
NHibernate unit testing with SQLite in-memory DB
2009-08-14T00:00:00+00:00
http://jasondentler.com/blog/2009/08/nhibernate-unit-testing-with-sqlite-in-memory-db
<p>While doing research for my next post, I ran across a recurring problem. Everyone wanted to use an in-memory SQLite database for their <a href="http://nhforge.org" target="_blank">NHibernate</a> unit tests.</p> <p>Evidently, there’s no way to get back to the in-memory database in it’s current state after all of the connections to that database have been closed. When you open another connection, you get a fresh blank database.</p> <p>Here’s the solutions I found while searching around.</p> <ul> <li><a href="http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx" target="_blank">Ayende just uses a single NHibernate session</a>, which usually only uses a single SQLite DB connection. In fact, he just uses one session per test fixture. I’m not that smart and I don’t know enough about the internals of NHibernate to be confident that I’m really testing what I think I’m testing. Using a fresh session and database for each test would make me a lot more confident. </li> <li>Krzysztof Kozmic has resorted to <a href="http://devlicio.us/blogs/krzysztof_kozmic/archive/2009/08/14/testing-with-nhibernate-and-sqlite.aspx" target="_blank">using a SQLite database stored on disk</a>. While it may be faster than blowing away and recreating a SQL Express database dozens of times, it’s still slower than using an in-memory database. Variations of this idea include storing the database on a MS-DOS 5.0-style RAM disk drive to recover some of the speed lost by using file I/O. Genius! Except, I’m not going to reconfigure my PC for a unit test. Sorry, it’s just not portable enough. That’s why the idea was rated down on Stack Overflow. </li> <li>Someone (gotta love the anonymous bloggers!) suggested <a href="http://notepad2.wordpress.com/2008/05/19/unit-testing-castle-active-record-using-sqlite-in-memory-database/" target="_blank">building a custom NHibernate DriverConnectionProvider</a> and overriding the GetConnection and CloseConnection functions so that once opened, the connection would never be closed. This seems a bit extreme to me, and doesn’t provide a mechanism to get a fresh database when we need one. </li> </ul> <p>Using the DriverConnectionProvider idea of maintaining a single connection, but with a controlled scope, I came up with this:</p> <pre class="brush:vbnet">Imports FluentNHibernate.Cfg
Imports FluentNHibernate.Cfg.Db
Imports FluentNHibernate.Mapping
Imports NHibernate
Imports NHibernate.Tool.hbm2ddl
Imports System.Data.SQLite
Public Class SQLiteDatabaseScope(Of TClassFromMappingAssembly)
Implements IDisposable
Private Const CONNECTION_STRING As String = "Data Source=:memory:;Version=3;New=True;"
Public Sub New()
BuildConfiguration()
End Sub
Private m_Connection As SQLiteConnection
Private m_SessionFactory As ISessionFactory
Private Sub BuildConfiguration()
m_SessionFactory = Fluently.Configure() _
.Database(GetDBConfig()) _
.Mappings(AddressOf GetMappings) _
.ExposeConfiguration(AddressOf BuildSchema) _
.BuildSessionFactory()
End Sub
Private Function GetDBConfig() As FluentNHibernate.Cfg.Db.IPersistenceConfigurer
Return SQLiteConfiguration.Standard _
.ConnectionString(Function(cs As ConnectionStringBuilder) cs.Is(CONNECTION_STRING))
End Function
Private Sub GetMappings(ByVal x As MappingConfiguration)
x.FluentMappings _
.AddFromAssemblyOf(Of TClassFromMappingAssembly)() _
.ExportTo(".")
End Sub
Private Sub BuildSchema(ByVal Cfg As NHibernate.Cfg.Configuration)
Dim SE As New SchemaExport(Cfg)
SE.Execute(False, True, False, GetConnection, Console.Out)
End Sub
Private Function GetConnection() As System.Data.SQLite.SQLiteConnection
If m_Connection Is Nothing Then
m_Connection = New SQLiteConnection(CONNECTION_STRING)
m_Connection.Open()
End If
Return m_Connection
End Function
Public Function OpenSession() As ISession
Return m_SessionFactory.OpenSession(GetConnection)
End Function
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free other state (managed objects).
If m_Connection IsNot Nothing Then m_Connection.Close()
m_Connection = Nothing
End If
' TODO: free your own state (unmanaged objects).
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class</pre>
<p>It’s the same idea as the DriverConnectionProvider, but with a different scope. We create and open a connection and maintain it for the lifespan of the SQLiteDatabaseScope object. So far, I haven't found an instance where NHibernate closes the connection.</p>
<p>Each instance of SQLiteDatabaseScope uses a different in-memory database, thanks to the New=True property in the connection string. You should be able to run your tests in parallel. You can’t do that with any of the other solutions.</p>
<p>The generic type parameter should be set to one of your fluent mapping classes. It’s used to tell Fluent NHibernate which assembly to scan for fluent mappings.</p>
<p>It’s extremely easy to use.</p>
<pre class="brush:vbnet">Imports NUnit.Framework
<TestFixture> _
Public Class SomeNHibernateTestFixture
<Test>
Public Sub SomeNHibernateTest()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using SessionOne = Scope.OpenSession
' Do some stuff here...
End Using
Using SessionTwo = Scope.OpenSession
' Do some more stuff using the same in-memory SQLite DB
End Using
End Using
End Sub
<Test>
Public Sub AnotherNHibernateTest()
Using Scope As New SQLiteDatabaseScope(Of CourseMapping)
Using SessionThree = Scope.OpenSession
' Do some stuff here to a new, freshly-built database...
End Using
End Using
End Sub
End Class</pre>
<p>Jason
<br />- Concerned the problem is not really that simple.</p>
<p> </p>
<p>Download the SQLiteDatabaseScope code in <a href="http://jasondentler.com/downloads/SQLiteDatabaseScope.vb.txt" target="_blank">Visual Basic</a> or <a href="http://jasondentler.com/downloads/SQLiteDatabaseScope.cs.txt" target="_blank">C#</a>. GoDaddy doesn’t like you to download .vb or .cs files, so don’t forget to take off the .txt extension before you add it to your project. </p>
How-To: Using the N* Stack, part 3
2009-08-13T00:00:00+00:00
http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3
This is the third installment in my series. In <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">part 1</a>, we downloaded our libraries and set up our solution. In <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2/" target="_blank">part 2</a>, we built our model. In this part, we’ll configure <a href="http://sourceforge.net/projects/nhibernate/" target="_blank">NHibernate</a> and set up our database mappings. We’ll also set up our database schema.
<h3>Java – A language of XML files loosely coupled by code.</h3>
Before we can talk about Fluent NHibernate, you need to know a little bit about setting up mappings in plain old NHibernate. In a typical NHibernate setup, you’ll have a bunch of mapping files like this:
<pre class="brush:xml"><?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="NStackExample.Address, NStackExample.Core" table="Address">
<composite-id>
<key-many-to-one name="Person" class="NStackExample.Person, NStackExample.Core" column="ID" />
<key-property name="Type" type="Int32" />
</composite-id>
<property name="City" type="String" length="255" />
<property name="Lines" type="String" length="255" />
<property name="State" type="String" length="2" />
<property name="Zip" type="String" length="10" />
</class>
</hibernate-mapping></pre>
You’ll have one of those for each of your entities. It’s left over from Java’s Hibernate project, and in my opinion, It’s a royal pain, complete with ruby scepter. Lucky for you, there’s a better way™.
<h3>A Better Way™: Fluent Mappings</h3>
With Fluent NHibernate, the mapping file above can be expressed using this class instead:
<pre class="brush:vbnet">Imports FluentNHibernate.Mapping
Public Class AddressMapping
Inherits ClassMap(Of Address)
Public Sub New()
UseCompositeId _
.WithKeyReference(Function(x As Address) x.Person) _
.WithKeyProperty(Function(x As Address) x.Type)
Map(Function(x As Address) x.Lines).WithLengthOf(255)
Map(Function(x As Address) x.City).WithLengthOf(255)
Map(Function(x As Address) x.State).WithLengthOf(2)
Map(Function(x As Address) x.Zip).WithLengthOf(5)
End Sub
End Class</pre>
<pre class="brush:csharp">using FluentNHibernate.Mapping;
namespace NStackExample.Data
{
public class AddressMapping : ClassMap<Address>
{
public AddressMapping()
{
UseCompositeId()
.WithKeyReference(x => x.Person)
.WithKeyProperty(x => x.Type);
Map(x => x.Lines).WithLengthOf(255);
Map(x => x.City).WithLengthOf(255);
Map(x => x.State).WithLengthOf(2);
Map(x => x.Zip).WithLengthOf(5);
}
}
}</pre>
It may look even more complicated than the XML mapping, but with Intellisense, it’s a breeze. Plus, there are no magic strings to worry about. When you change a property name using a refactor tool, your mapping won’t be left out of sync.
Now that you have the basic idea, let’s get back on track.
<h3>Where?</h3>
Since the database connection, NHibernate configuration, entity mappings, and DAO implementations are really just implementation details of our chosen ORM, they should go in a separate assembly.
<ol>
<li>Make a new Class Library project called NStackExample.Data</li>
<li>In the new Data project, add references to your core project, NHibernate.dll and FluentNHibernate.dll</li>
<li>Add a reference to System.Configuration.dll so we can easily retrieve some application settings later.</li>
<li>Also, the web project needs a reference to the data project.</li>
</ol>
Now, let’s make our mappings.
<pre class="brush:vbnet">Imports FluentNHibernate.Mapping
Public Class CourseMapping
Inherits ClassMap(Of Course)
Public Sub New()
Id(Function(x As Course) x.ID).GeneratedBy.GuidComb()
Map(Function(x As Course) x.Subject).Not.Nullable.WithLengthOf(4).UniqueKey("CourseNaturalKey")
Map(Function(x As Course) x.CourseNumber).Not.Nullable.WithLengthOf(4).UniqueKey("CourseNaturalKey")
Map(Function(x As Course) x.Title).Not.Nullable.WithLengthOf(255)
Map(Function(x As Course) x.Description).Not.Nullable.WithLengthOf(1024)
Map(Function(x As Course) x.Hours).Not.Nullable()
HasMany(Function(x As Course) x.Sections) _
.AsSet() _
.WithForeignKeyConstraintName("CourseSections")
End Sub
End Class</pre>
<pre class="brush:csharp">using NStackExample;
using FluentNHibernate.Mapping;
namespace NStackExample.Data
{
public class CourseMapping : ClassMap<Course>
{
public CourseMapping()
{
Id(x => x.ID).GeneratedBy.GuidComb();
Map(x => x.CourseNumber)
.Not.Nullable()
.WithLengthOf(4)
.UniqueKey("CourseNaturalKey");
Map(x => x.Subject)
.Not.Nullable()
.WithLengthOf(4)
.UniqueKey("CourseNaturalKey");
Map(x => x.Title)
.Not.Nullable()
.WithLengthOf(255);
Map(x => x.Description)
.Not.Nullable()
.WithLengthOf(1024);
Map(x => x.Hours)
.Not.Nullable();
HasMany(x => x.Sections)
.AsSet()
.WithForeignKeyConstraintName("CourseSections");
}
}
}</pre>
Most of this is self-explanatory and works exactly like you would expect.
Our mapping class inherits from ClassMap(Of Course). ClassMap is the specific type that Fluent NHibernate searches for when looking for mappings. In this case, it signifies that this class provides the mapping for our Course entity. In the constructor, we define our specific mapping for each property.
<ul>
<li>Id sets up the persistent object identifier (POID). This is basically the primary key for the table. If you have more than one property in the primary key, as in the case of natural keys, go with UseCompositeId like in the address example above. Using multi-part keys isn’t really suggested and to my knowledge, isn’t fully supported by Fluent NHibernate.</li>
<li>GeneratedBy specifies the POID generator. How will you assign your keys? In my case, I use GuidComb. I get all of the benefits of guid identifiers, but I don’t fragment my database index nearly as much. You can read up on it more in <a href="http://nhforge.org/blogs/nhibernate/archive/2009/05/21/using-the-guid-comb-identifier-strategy.aspx" target="_blank">Davy Brion‘s post on the NHForge blog</a>.</li>
<li>Map simply maps a property to a database column. You can specify Not.Nullable and WithLengthOf as necessary.</li>
<li>UniqueKey specifies a unique index on the column. If you specify the same name on several columns, all of those columns will be part of the same unique index. In this example, we are forcing our natural key to be unique. Each combination of subject and course number must be unique. There can only be one ENGL 1301 course. Thank goodness.</li>
<li>HasMany defines a one-to-many relationship. You can specify the exact behavior of the collection. You have several options here, but the two types I use almost exclusively are Set and Bag.
<ul>
<li>AsSet doesn’t allow duplicate items.</li>
<li>With AsBag, duplicates are allowed.</li>
</ul>
</li>
</ul>
By default, all relationships are lazy-loaded. This means that when you fetch a course from the database, the associated sections aren’t fetched right away. It works just like you would expect: They aren’t fetched until you access the Sections property. If you never access the Sections property, those sections are never fetched from the database, which can greatly improve performance. This is all made possible with proxies, but that’s another series of posts.
Now let’s map the sections:
<pre class="brush:vbnet">Imports FluentNHibernate.Mapping
Public Class SectionMapping
Inherits ClassMap(Of Section)
Public Sub New()
Id(Function(x As Section) x.ID).GeneratedBy.GuidComb()
Map(Function(x As Section) x.FacultyName).WithLengthOf(255)
Map(Function(x As Section) x.RoomNumber).WithLengthOf(10)
Map(Function(x As Section) x.SectionNumber) _
.WithLengthOf(4) _
.Not.Nullable() _
.UniqueKey("SectionNaturalKey")
References(Function(x As Section) x.Course) _
.Not.Nullable() _
.UniqueKey("SectionNaturalKey")
References(Function(x As Section) x.Term) _
.Not.Nullable() _
.UniqueKey("SectionNaturalKey")
HasMany(Function(x As Section) x.StudentSections) _
.AsSet() _
.WithForeignKeyConstraintName("SectionStudentSections")
End Sub
End Class</pre>
The References function maps the Many-to-one relationship. Think of it as the other side of our one-to-many relationship. It is the reference from the child – section - back to it’s parent - course.
For homework, finish mapping all of the entities.
I bet you’re thinking this post is getting long considering we haven’t even started building the database. Well don’t worry. NHibernate will do that for us.
<h3>8 hours or 8 minutes?</h3>
Before I discovered NHibernate, I would spend at least a day setting up my database. It was insane. It drove me insane. I bet it drives you insane. It ends today.
<strong>Disclaimer</strong>: If you are trying to use an existing shared legacy database, the chances of your existing DB schema working without some tweaking are slim. <a href="http://nhforge.org/blogs/nhibernate/archive/2009/06/26/database-the-eliot-ness-of-it.aspx" target="_blank">This post by Fabio Maulo</a> explains your options.
First, let’s configure NHibernate. The Fluent NHibernate Wiki has <a href="http://wiki.fluentnhibernate.org/show/DatabaseConfiguration" target="_blank">a great page</a> explaining the fluent configuration of NHibernate.
<pre class="brush:vbnet">Imports NHibernate
Imports NHibernate.Tool.hbm2ddl
Imports FluentNHibernate.Cfg
Imports System.Configuration
Imports System.IO
Public Class Configuration
Private m_SchemaPath As String
Private m_Factory As ISessionFactory
Public Function Configure() As Configuration
m_SchemaPath = ConfigurationManager.AppSettings("NStackExample.Data.Configuration.SchemaPath")
m_Factory = Fluently.Configure _
.Database(Db.MsSqlConfiguration.MsSql2005 _
.ConnectionString(Function(x As Db.MsSqlConnectionStringBuilder) _
x.FromConnectionStringWithKey("NStackExample.Data.Configuration.DB"))) _
.Mappings(Function(x As MappingConfiguration) _
x.FluentMappings.AddFromAssemblyOf(Of CourseMapping)() _
.ExportTo(m_SchemaPath)) _
.ExposeConfiguration(AddressOf BuildSchema) _
.BuildSessionFactory()
Return Me
End Function
Private Sub BuildSchema(ByVal Cfg As NHibernate.Cfg.Configuration)
Dim SchemaExporter As New NHibernate.Tool.hbm2ddl.SchemaExport(Cfg)
SchemaExporter.SetOutputFile(Path.Combine(m_SchemaPath, "schema.sql"))
SchemaExporter.Create(False, True)
End Sub
Public Function OpenSession() As ISession
If m_Factory Is Nothing Then Configure()
Return m_Factory.OpenSession
End Function
End Class</pre>
<pre class="brush:csharp">using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using System.IO;
using System.Configuration;
namespace NStackExample.Data
{
public class Configuration
{
private ISessionFactory m_Factory;
private string m_SchemaPath;
public Configuration Configure()
{
m_SchemaPath = ConfigurationManager.AppSettings["NStackExample.Data.Configuration.SchemaPath"];
m_Factory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(
x => x.FromConnectionStringWithKey("NStackExample.Data.Configuration.Db")))
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<CourseMapping>()
.ExportTo(m_SchemaPath))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
return this;
}
private void BuildSchema(NHibernate.Cfg.Configuration cfg)
{
SchemaExport SchemaExporter = new SchemaExport(cfg);
SchemaExporter.SetOutputFile(Path.Combine(m_SchemaPath, "schema.sql"));
SchemaExporter.Create(true, false);
}
public ISession OpenSession()
{
if (m_Factory == null) Configure();
return m_Factory.OpenSession();
}
}
}</pre>
The configuration falls in to two sections: Database and Mappings. In our case, the database is SQL 2005 and the connection string is read from a connection string element in the web.config. All of the mappings are fluent, not auto-mapped. Notice that we are exporting our mappings to a directory specified in the appsettings section of the web.config. This will convert our fluent mappings to individual hbm.xml files. This is great for debugging the mappings, especially when asking for NHibernate help online.
We have one additional item. We’re using the ExposeConfiguration method to call our BuildSchema function, passing in our complete NHibernate configuration.
In BuildSchema, we use a great hidden tool in NHibernate: the schema export. This amazing class will build your database for you. The create function takes two boolean parameters. The first specifies if the schema should be written out to a ddl file – a database script to build all of the tables, keys, indexes, and relationships in your database. The second boolean parameter specifies if the script should be executed against the specified database.
It’s that easy.
<strong>Two warnings:</strong>
<ol>
<li>Executing this script will drop and recreate every table associated with your model. That can be devastating in a production environment.</li>
<li>The script doesn’t start with a a “use [databasename]” statement, so if you’re not careful, when you execute it, you’ll build everything in the master database.</li>
</ol>
One last note: As with any project, you will have to adapt as you build. These mappings are not exactly what we use in the final build. I can guarantee our model will change significantly. I will take you through those changes as they happen, and explain the reasons behind them.
I’ve decided not to post the complete source code at this stage. Instead, I leave the remaining mappings as an exercise for you, the reader. They will be included in the next source release.
In the next post, I’ll show you how to test your mappings – including querying, reading from and writing to the database.
Jason
- Mapped out. Good night.
P.S. – Special thanks to Tuna, Fabio, and Oren for the feedback, answers to stupid questions, and great advice!
Windows 7 x64 upgrade
2009-08-12T00:00:00+00:00
http://jasondentler.com/blog/2009/08/windows-7-x64-upgrade
Today, I'm upgrading my PC to Windows 7 64-bit. So far, the process has been quick and painless - which is pretty much the best possible outcome for system upgrades (and medical tests).
Evidently I forgot to copy my music collection up to the file server before blowing away my partition. I guess I'll be re-ripping this afternoon. Now I remember why I always spend the extra $2 to buy a physical CD from Amazon instead of just the bits.
Anywho. I'll be looking in to cloud backup solutions before I attempt anything like this at home. If anyone has suggestions, I'm open to ideas.
I was tweeted by the mother ship in my sleep
2009-08-09T00:00:00+00:00
http://jasondentler.com/blog/2009/08/i-was-tweeted-by-the-mother-ship-in-my-sleep
<p><a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb5.png" width="244" height="177" /></a> </p> <p>Actually, I was awake, but offline. When I posted last night, I had exactly zero RSS subscribers and one twitter follower – a family member. I woke up this morning to find I had blog comments, RSS subscribers, and twitter followers. People – not just people, programmers - actually read that mess I posted. The pressure is on now.</p> <p>So, thank you ScottGu for the great press! The second post in the series will be coming shortly.</p>
How-To: Using the N* Stack, part 2
2009-08-09T00:00:00+00:00
http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-2
Last Saturday, I posted the <a href="http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1/" target="_blank">first part in a series</a> about building an <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> application from the ground up using <a href="http://sourceforge.net/projects/nhibernate/" target="_blank">NHibernate</a> and <a href="http://ninject.org/" target="_blank">Ninject</a>. It dealt with setting up the structure of your solution and referencing some 3rd party assemblies.
In part 2, we’re going to set up the persistence object model. The persistence object model is a set of objects that we use to persist (save) data to the database.
<strong>Warning:</strong> This is a sample application. There are widely varying opinions on the correct structure for these types of applications. As with most advanced subjects in the ALT.NET space, <a href="http://ayende.com/Blog/Default.aspx" target="_blank">Ayende</a> has <a href="http://ayende.com/Blog/archive/2009/08/02/your-domain-model-isnrsquot-in-the-entity-relationship-diagram.aspx" target="_blank">some great information</a> on the difference between a persistence object model and a domain model. For the purposes of this series, they’re the same thing.
First, we build the structure of our persistence model as plain old CLR objects (POCO). I like to do this in the Visual Studio class designer. It helps keep me focused on the high-level entities and relationships instead of wandering off to do detailed implementation code.
Here’s the model we’ll start with:
<a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image6.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb6.png" border="0" alt="image" width="528" height="610" /></a>
Let’s look at the relationships between courses and sections. We have a one to many relationship from a Course to it’s Sections represented by an ICollection(Of Section) property in Course. We also have a many-to-one relationship from each section back to it’s Course represented by the Course property on Section.
<pre class="brush:vbnet">Public Class Course
Public Property Sections() As ICollection(Of Section)
Get
End Get
Set(ByVal value As ICollection(Of Section))
End Set
End Property
End Class
Public Class Section
Public Property Course() As Course
Get
End Get
Set(ByVal value As Course)
End Set
End Property
'Other properties here...
End Class</pre>
<pre class="brush:csharp">public class Course
{
public ICollection<Section> Sections {
get { }
set { }
}
}
public class Section
{
public Course Course {
get { }
set { }
}
//Other properties here...
}</pre>
Now that we have all of that built, there’s a couple of small requirements to use these classes with NHibernate.
<ol>
<li>All properties and methods must be overridable. That’s virtual for your C# folks.</li>
<li>Unless you’re using a dependency injection bytecode provider, you need a parameter-less constructor. If you don’t know what a bytecode provider is, don’t worry about it. We’ll get in to it later on in the series. If you don’t have any constructors, you’re fine. There’s an implied parameterless constructor. As soon as you add a constructor with parameters, you’ll need to create one without parameters, just for NHibernate.</li>
<li><span style="text-decoration: line-through;">You need some sort of identity property for your database primary key. This can be inherited from a base class, which is exactly what we’re going to do.</span> Edit: Not true. Thanks for the correction Ayende!</li>
<li>In the case of readonly properties, you have some options. You can tell NHibernate your naming convention for backing fields. I don’t like this. I prefer to make my properties read/write and make the setter protected. If you’re new to NHibernate, you’ve probably never seen this before.
<pre class="brush:vbnet">Public Class Course
Inherits Entity
Private m_Sections As ICollection(Of Section) = New HashSet(Of Section)
Public Overridable Property Sections() As ICollection(Of Section)
Get
Return m_Sections
End Get
Protected Set(ByVal value As ICollection(Of Section))
m_Sections = value
End Set
End Property
End Class</pre>
<pre class="brush:csharp">public class Course : Entity
{
private ICollection<Section> m_Sections = new HashSet<Section>();
public virtual ICollection<Section> Sections {
get { return m_Sections; }
protected set { m_Sections = value; }
}
}</pre>
This is how I set up all of my collection properties. You can manipulate the contents of the collection, but you can't replace it with another instance without inheriting this class and overriding the property. If you were to make this property readonly, you'd have to configure NHibernate to write to m_Sections using reflection. It's sort of a pain, and completely unnecessary. This is easier and accomplishes the same end result.
Also, notice that we're inheriting from a class called Entity. More on that later.</li>
</ol>
Let's talk about the database for a minute. Each of these entity classes will eventually become a database table. What will you use for your primary keys? <a href="http://fabiomaulo.blogspot.com/2009/02/nh210-generators-behavior-explained.html" target="_blank">Fabio Maulo</a> has a great post on the different NHibernate primary key generators. He also has <a href="http://fabiomaulo.blogspot.com/2008/12/identity-never-ending-story.html" target="_blank">this post</a> about why identity columns probably are not the best choice.
So what’s a good choice? Well, that’s a matter of opinion. Thanks to NHibernate, I don’t go spelunking through the database much anymore, so I like guids. You really can use what you like, or rather, what your DBA likes.
Now, where are you going to put these primary keys in your objects? In my opinion, this is really a persistence detail – meaning your objects shouldn’t really be dealing with it. That’s why we’re going to keep it hidden away in the base class. Remember, we’re inheriting from Entity.
<pre class="brush:vbnet">Public MustInherit Class Entity
Private m_ID As Guid
Public Overridable Property ID() As Guid
Get
Return m_ID
End Get
Protected Set(ByVal value As Guid)
m_ID = value
End Set
End Property
End Class</pre>
<pre class="brush:csharp">public abstract class Entity
{
private Guid m_ID;
public virtual Guid ID {
get { return m_ID; }
protected set { m_ID = value; }
}
}</pre>
That’s it for today’s post. In part 3, we’ll configure NHibernate and set up our database. For homework, we’re going to flesh out the other properties in our persistence model. Check out the source code in <a href="/downloads/NStackExample.Part2.VBNET.zip" target="_blank">Visual Basic.NET</a> or <a href="/downloads/NStackExample.Part2.CSHARP.zip" target="_blank">C#.</a>
How-To: Using the N* stack, part 1
2009-08-08T00:00:00+00:00
http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-1
This is the first post in a series where I show you step-by-step how to get your first ASP.NET MVC website up off the ground. By the end of this series, we’ll have a working web application for registering community college students. More importantly, you'll have a template you can easily follow for your own projects.
In this first post, I’ll show you how to set up your visual studio solution.
In this series, we’ll use these tools:
<ul>
<li><strong><a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a></strong> is a free, fully Microsoft-supported product that, unlike ASP.NET WebForms, gives you complete control over your application. You can use the Web Platform Installer or download the MSI installer package directly.</li>
<li><strong><a href="http://www.codeplex.com/MVCContrib" target="_blank">MVCContrib</a></strong> – This is the contrib project for ASP.NET MVC. It adds additional functionality to and makes ASP.NET MVC easier to use.</li>
<li><strong><a href="http://jquery.com/" target="_blank">jQuery</a></strong> – This is an open-source javascript library that does just about everything, and supports every major modern browser out there. Yes, you hate javascript. You’re going to love jQuery. I promise. This is included in the ASP.NET MVC download.</li>
<li><strong><a href="http://sourceforge.net/projects/nhibernate/" target="_blank">NHibernate 2,1</a></strong> is a well-known, mature, open source object relational mapper (ORM). It helps you get on with writing you application, instead of spending days, weeks, or even months writing a data access layer.</li>
<li><strong><a href="http://fluentnhibernate.org/downloads" target="_blank">Fluent NHibernate</a></strong> – This is a library for configuring NHibernate using an english-like syntax. It saves you from hacking through dozens of XML configuration files. Scroll to the bottom of the downloads page and get the latest compiled binaries.</li>
<li><strong><a href="http://ninject.org/" target="_blank">Ninject</a></strong> is my personal favorite dependency injection (DI) / inversion of control (IoC) framework. It allows you to automatically wire up services to your objects. If you’ve never done DI or IoC before, you’re going to have a great “ah-ha!” moment. We’ll be using version 1.</li>
</ul>
You will also need:
<ul>
<li>.NET Framework 3.5 SP1</li>
<li>Visual Studio 2008 SP1. The Web Dev Express version may also work. I haven’t tried it.</li>
<li>The latest version of NUnit</li>
<li>Any major database supported by NHibenate. This can range from Oracle to SQL Server to MySQL to SQLite. I’ll be using SQL server in my examples, but if you have a favorite, you can easily use that instead.</li>
</ul>
I also suggest you get some kind of source control. You’ll want to play around and experiment as we go along.
OK. You’ve downloaded all of that? Good. Let’s talk terminology for a minute.
<ul>
<li><strong>MVC</strong> stands for <strong>Model-View-Controller</strong>. This separation of responsibilities allows you greater flexibility to adapt and change your application.</li>
<li><strong>Model</strong> – This term refers to all of your entities – your business objects. In terms of a billing application, this would be your invoices, invoice items, customers, products, etc. – all of the “real-world things” your application represents.</li>
<li><strong>View</strong> – Each view presents a specific business object in a specific way. For example, you may have a view for editing customer data and another for displaying an invoice. You can also think of views as the pages that make up your application.</li>
<li><strong>Controller</strong> – Controllers are the glue that bind a view to a specific entity in your model. They are also responsible for all of the flow of your application from page to page.</li>
<li><strong>Inversion of Control</strong> (<strong>IoC</strong>) is the concept that your objects do not explicitly create the services that they need. Instead, they get them from some container of services. Hence, the inversion. Your classes don’t specify a specific implementation of the service, only the type of service they need – an interface. This loose coupling allows you to easily swap out implementations of those services without having to touch every class that uses them. I’ve seen two major flavors of IoC: Service Locator and Dependency Injection.</li>
<li>A <strong>Service Locator</strong> is a central container where you specify which implementations of each service your application will use. Your objects request service implementations from the service locator. A service locator is typically a singleton, which is why I don’t like it.</li>
<li><strong>Dependency Injection</strong> (<strong>DI</strong>) is a method of wiring your objects to the services they depend on as the object is built. These services are typically passed in as parameters on the object’s constructor. The object itself is built by the DI framework, in this case, Ninject. The process of building dependencies can be many layers deep. The <a href="http://dojo.ninject.org/Dependency%20Injection%20By%20Hand.ashx" target="_blank">Ninject Dojo</a> has a great tutorial on dependency injection. If you’re new to IoC, it’s a great place to start learning. Once you have the “ah ha!” moment, the migraine will stop and you’ll never look at code the same again. I promise.</li>
</ul>
<h3>Setting up the solution</h3>
<em>Disclaimer: This is how I have learned to set up my projects. I’m sure others have differing opinions. I’d love to hear them. I don’t claim to be an expert, just a curious professional looking to improve. </em>
Setting up the project is fairly straight-forward. We’ll do almost everything through Visual Studio. Just follow these steps.
<ol>
<li>
<h4>Create the solution and web project</h4>
In Visual Studio, start a new ASP.NET MVC Web Application. This template is added to Visual Studio when you install ASP.NET MVC. I’ll be calling my solution NStackExample.<a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image.png">
<img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb.png" border="0" alt="image" width="534" height="293" /></a>
There’s a few things to note here. First, we’re creating a solution directory. Second, notice how we’ve appended .Web to the name of our web project, but not the solution.
This web project will contain all of the views. Despite the implied direction from Microsoft through the ASP.NET MVC template, it won’t contain the model or the controllers.</li>
<li>
<h4>Create a library directory</h4>
Inside your solution directory, create a directory for all 3rd party libraries used in your project. I call mine Solution Items. The name you give it isn’t as important as the fact that you have one. So, in the example shown above, I would create the directory C:UsersJasonDocumentsVisual Studio 2008ProjectsNStackExampleSolution items. Copy these 15 assemblies to the library directory:
<ul>
<li>From MVCContrib:
<ul>
<li>MVCContrib.dll</li>
<li>Microsoft.Web.Mvc.dll</li>
<li>System.Web.Abstractions.dll</li>
<li>System.Web.Mvc.dll</li>
<li>System.Web.Routing.dll</li>
</ul>
</li>
<li>From NHibernate:
<ul>
<li>Antlr3.Runtime.dll</li>
<li>Iesi.Collections.dll</li>
<li>log4net.dll</li>
<li>NHibernate.dll</li>
<li>Castle.Core.dll</li>
<li>Castle.DynamicProxy2.dll</li>
<li>NHibernate.Bytecode.Castle.dll</li>
</ul>
</li>
<li>FluentNHibernate.dll from Fluent NHibernate</li>
<li>From Ninject:
<ul>
<li>Ninject.Core.Dll</li>
<li>Ninject.Framework.Mvc.Dll</li>
</ul>
</li>
</ul>
</li>
<li>
<h4>Create the core project</h4>
This is your main project. It will contain your model, as well as interfaces for any services and strategies your application will use. It will not contain the implementation of any of those services. Those go in separate, easily replaceable assemblies.
Add a new “Class Library” project to your solution. We’ll call this project NStackExample.Core.
Now, right click on the project and select properties, then click on the Application tab on the side. In the root namespace field, remove .Core.
<a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb2.png" border="0" alt="image" width="554" height="57" /></a>
We’re doing this so our entities will be named NStackExample.Entity1, NStackExample.Entity2, etc. but the assembly will be NStackExample.Core.dll, which better describes it’s purpose.</li>
<li>
<h4>Create the controller project</h4>
Next, create another project specifically for the controllers of your MVC project. We’re going to call it NStackExample.Controllers. Yes, the Microsoft ASP.NET MVC project template already has a folder for them. We’re not going to use that folder because I think they should be better separated from the content of your website.</li>
<li>
<h4>Clean up your projects</h4>
Delete all of these:
<ul>
<li>The Class.vb or Class.cs files in the Core and Controllers projects.</li>
<li>In the NStackExample.Web project, delete:
<ul>
<li>The Controllers folder and all of it's contents.</li>
<li>The Models folder</li>
<li>The Microsoft AJAX script libraries in the Scripts folder</li>
<li>The Home and Account folders inside the Views folder</li>
<li>The LogOnUserControl in the Views folder</li>
</ul>
</li>
</ul>
<a href="http://jasondentler.com/blog/wp-content/uploads/2009/08/image4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/image_thumb4.png" border="0" alt="image" width="410" height="771" /></a></li>
<li>
<h4>Set up your references</h4>
This is pretty straight forward.
<ol>
<li>First, in your web project, remove the references to System.Web.Abstractions, System.Web.Mvc, and System.Web.Routing.</li>
<li>Next, in your web project, from the library directory we created in step 2, add references to these 10 assemblies:
<ul>
<li>log4net.dll</li>
<li>Microsoft.Web.Mvc.dll</li>
<li>MvcContrib.dll</li>
<li>NHibernat.Bytecode.Castle.dll</li>
<li>NHibernate.dll</li>
<li>Ninject.Core.dll</li>
<li>Ninject.Framework.Mvc.dll</li>
<li>System.Web.Abstractions.dll</li>
<li>System.Web.Mvc.dll</li>
<li>System.Web.Routing.dll</li>
</ul>
</li>
<li>In the web project, add references to the controllers project and the core project.</li>
<li>In the controllers project, add references to these 3 assemblies:
<ul>
<li>log4net.dll</li>
<li>MvcContrib.dll</li>
<li>System.Web.Mvc.dll</li>
</ul>
</li>
<li>In the controllers project, add a reference to the core project.</li>
</ol>
</li>
</ol>
Did you notice how we didn’t add any references in our core project? That’s intentional. When a project needs to reference your model or service interfaces, you don’t want to have required dependencies on other libraries and frameworks.
That’s it. Your solution is set up and you’re ready to start coding. In the next post, we’ll start building the model, configure NHibernate, and set up the database.
Jason
- Blogged-out for the night
Hibernating Ninjas and Entity Ninjection AddIn
2009-08-07T00:00:00+00:00
http://jasondentler.com/blog/2009/08/hibernating-ninjas-and-entity-ninjection-addin
<img class="alignright size-medium wp-image-99" title="injection" src="http://jasondentler.com/blog/wp-content/uploads/2009/08/injection-299x198.jpg" alt="injection" width="299" height="198" />As I posted before, NHibernate 2.1 allows you to <a href="http://jasondentler.com/blog/2009/08/nhibernate-2-1-released/">inject dependencies in to your entities</a> through the constructor. The idea is that when NHibernate rehydrates your object graph, it uses your favorite IoC container to inject whatever strategies and services your entities may require.
The <a href="http://code.google.com/p/unhaddins/">Unofficial AddIns for NHibernate</a> project has implementations of NHibernate's IBytecodeProvider interface to do Entity DI with Castle and Spring. Using these as a template, I've written an add-in for Entity DI using Ninject v2.
The code for this add-in basically falls in to two categories:
<ol>
<li>Make NHibernate stop whining about parameters on the constructors.</li>
<li>Creating instances of entities as they are being rehydrated from the database.</li>
</ol>
<h3>Constructor Parameters - Oh, the humanity!</h3>
We all know NHibernate makes a big freakin' deal out of certain things - virtual / overridable methods and properties, and parameterless constructors. When you do constructor DI, the constructor will have parameters. It's a fact. Yes, you can inject your dependencies through properties, but don't do it. You'll spend months chasing NullReferenceExceptions.
So, how do we stop NHibernate from puking on entities that don't have a parameterless constructor? Simple - We override the methods that do those checks. Thanks to some serious refactoring in NHibernate 2.1, it's all in two places.
<ol>
<li>DynProxyTypeValidator's CheckHasVisibleDefaultConstructor method</li>
<li>ReflectionOptimizer's ThrowExceptionForNoDefaultCtor method</li>
</ol>
So, we sub-class those objects and override those methods to do nothing. There's some other minor plumbing. Check out ProxyFactoryFactory in the attached source.
<h3>What's this BytecodeProvider thing anyway?</h3>
From <a href="http://nhforge.org/blogs/nhibernate/archive/2008/12/12/entities-behavior-injection.aspx">Fabio Maulo's blog</a>:
<blockquote>The BytecodeProvider has two responsibility: provide the ProxyFactoryFactory and provide the ReflectionOptimizer.</blockquote>
That's exactly what we're doing.
Besides providing our new ProxyTypeValidator, the ProxyFactoryFactory also returns an implementation of IProxyFactory. Since Ninject doesn't do proxies, we have to wire in a proxy generator. Well, what's a DI framework good for, if not to wire in services. IProxyFactory is fetched from the kernel. This means you can use Ninject for DI and still have your choice of proxy factories: Castle, Spring, or Linfu, so far.
The reflection optimizer is responsible for creating instances of our entities as they're being rehydrated from the database. This is where we get in to the second part of code.
<h3>Let's make some entities</h3>
Because Ninject has automatic self-binding baked in, this part is also insanely easy. Here's the ReflectionOptimizer function where all of the magic happens:
<pre class="brush:csharp"> public override object CreateInstance()
{
return kernel.Get(mappedType);
}</pre>
That's it. Yes. Really. It's that easy.
Well, not quite <strong>that</strong> easy. This changes the requirements for your entites in one very subtle and non-obvious way. In previous versions, and by default in this version, NHibernate always uses the parameterless constructor.
When using the NinjectBytecodeProvider, unless you decorate your entities with the Inject attribute, the constructor with the <strong>most</strong> parameters will be used. Remember - Unless you explicitly tell it otherwise, Ninject will choose the most complicated constructor it can find, even if it can't resolve all of the dependencies.
<h3>Great! What now?</h3>
I've submited this code to the <a href="http://code.google.com/p/unhaddins/issues/detail?id=10">uNHAddIns project</a> and <a href="http://groups.google.com/group/ninject/browse_thread/thread/cc0b7739929217c7?hl=en">posted about it</a> in the Ninject group. Until it's posted there, you can <a href="/downloads/uNhAddIns.NinjectAdapters.zip">download it here</a>.
That's all the time we have today. Tune in to my next post, where I'll show you how to build your own ASP.NET MVC project, and use this bytecode provider.
Jason
- Ninjecting entities since 2009
NHibernate 2.1 released
2009-08-01T00:00:00+00:00
http://jasondentler.com/blog/2009/08/nhibernate-2-1-released
<a href="http://ayende.com/Blog/archive/2009/07/20/nhibernate-2.1-is-out.aspx">NHibernate 2.1 is out</a>, and it has all kinds of good stuff™.
<ul>
<li>You don't need parameterless constructors on your entities anymore! No more of this mess:
<pre class="brush:vbnet"> ''' <summary>
''' NHibernate-only. Do not use.
''' </summary>
''' <remarks></remarks>
Public Sub New()
End Sub
''' <summary>
''' Real constructor
''' </summary>
''' <remarks></remarks>
Public Sub New(param1 As String, param2 As Date)
End Sub</pre>
</li>
<li>Dependency injection for entities.
Now, just inject your services right in to the constructor of the entity, instead of having to go get them every time you call your entity's methods.<br /> This:
<pre class="brush:vbnet">
Public Sub New()
End Sub
Public Function ChangePassword(oldPassword As String, newPassword As String, passwordHasher As IPasswordHashService) As String
' Do stuff
End Function
</pre>
becomes:
<pre class="brush:vbnet">
Public Sub New(passwordHasher As IPasswordHashService)
m_PasswordHasher = passwordHasher
End Sub
Public Function ChangePassword(oldPassword As String, newPassword As String) As String
'Do Stuff
End Function
</pre>
The benefit is that you don't have to inject your IPasswordHashService in to everything that calls ChangePassword.
</li>
<li>Finally, support for HashSet(Of T) instead of that weird little IESI implementation. Since .NET doesn't come with an ISet(Of T) interface, use ICollection(Of T).</li>
<li>Works with new SQL 2008 data types: Date, Time, and DateTimeOffset.</li>
</ul>
- Jason
Hibernating
LINQ to NHibernate 1.0 released
2009-07-31T00:00:00+00:00
http://jasondentler.com/blog/2009/07/linq-to-nhibernate-1-0-released
<a href="http://devlicio.us/blogs/tuna_toksoz/archive/2009/07/26/nhibernate-linq-released.aspx">Tuna Toksoz</a>, <a href="http://chadly.net/post/2009/07/27/NHibernateLinq-10-is-out-and-about.aspx">Chad Lee</a>, and <a href="http://ayende.com/Blog/archive/2009/07/26/nhibernate-linq-1.0-released.aspx">Oren Eini a.k.a Ayende</a> have released LINQ to NHibernate 1.0. This version is still based on and limited by the criteria API of NHibernate, and still part of the NHContrib project.
Which one would you rather use?
<pre class="brush:vbnet">
Function Authenticate(userName As String, hashedPassword As String) As Identity
Dim Query = From Identity In Accounts _
Where Identity.UserName = userName _
AndAlso Identity.PasswordHash = hashedPassword
Return Query.FirstOrDefault
End Function
</pre>
<pre class="brush:vbnet">
Function Authenticate(userName As String, hashedPassword As String) As Identity
Dim Query = m_Session.CreateCriteria(GetType(Identity)) _
.Add(Expression.And( _
Expression.Eq("UserName", userName), _
Expression.Eq("PasswordHash", hashedPassword)) _
.List().Cast(Of Identity)
Return Query.FirstOrDefault
End Function
</pre>
Aren't you tired of using magic strings in the criteria API?
<a href="http://blogs.imeta.co.uk/sstrong/archive/2009/06/11/708.aspx">Steve Strong</a> has done a TON of work on the <a href="http://ayende.com/Blog/archive/2009/02/22/nhibernate-hql-ast-parser.aspx">HQL abstract syntax tree parser</a>, which is a prerequisite for the more powerful HQL version LINQ to NHibernate that will be part of the main NHibernate project, not NHContrib. His work was sponsored by <a href="http://imeta.co.uk/">iMeta</a>. The HQL AST has made it in to recently-released NHibernate 2.1, so the HQL version of LINQ to NHibernate can't be too far behind.
- Jason
LINQing like mad!
Hello World!
2009-07-31T00:00:00+00:00
http://jasondentler.com/blog/2009/07/hello-world-2
Hi boys and girls. Today, we're going to talk about computer programming, technology, and <del style="color: red; text-decoration: line-through;">surviving</del> thriving in an IT department.
As you might have guessed by the blog title, I'm a fan of BASIC programming languages. I've been programming on PCs since about 4th grade when I first started tinkering with BASIC on my family's 286 IBM PC clone running DOS 3.3. The language has come a long way since line numbers and GOSUBs.
Just to be clear, I'm not one of those VB weenies who makes a living by hammering out form after form with drag-and-drop designers. I write code. I create. I use the whole language, not just the clicky-widgets and IDE dohickeys.
So, stay tuned for some great info on advanced Visual Basic.NET, and programming and technology in general.
- Jason
Pro coder, amateur blogger
P.S. The blog title is intentionally misspelled.