<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gr="http://www.google.com/schemas/reader/atom/" xmlns:idx="urn:atom-extension:indexing" idx:index="no" gr:dir="ltr"><!--
Content-type: Preventing XSRF in IE.

--><generator uri="http://www.google.com/reader">Google Reader</generator><id>tag:google.com,2005:reader/user/09819328367926521350/label/nhibernate</id><title>"nhibernate" via Marc Climent in Google Reader</title><gr:continuation>CMGI8-TLyJwC</gr:continuation><author><name>Marc Climent</name></author><updated>2011-01-26T14:05:13Z</updated><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/climens_nhibernate" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="climens_nhibernate" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gr:crawl-timestamp-msec="1296050713789"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:770">tag:google.com,2005:reader/item/c2385eac8c870751</id><category term="NHibernate" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/NHibernate/default.aspx" /><category term="fluent configuration" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/fluent+configuration/default.aspx" /><title type="html">Loquacious Configuration in NHibernate 3</title><published>2011-01-21T21:54:07Z</published><updated>2011-01-21T21:54:07Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/gEWGJL4ArgE/loquacious-configuration-in-nhibernate-3.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2011/01/21/loquacious-configuration-in-nhibernate-3.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;[This article was originally published on my personal blog &lt;a href="http://jameskovacs.com/2011/01/21/loquacious-configuration-in-nhibernate-3/"&gt;here&lt;/a&gt;. I hereby grant myself permission to re-publish it on NHForge.org.]&lt;/p&gt;  &lt;p&gt;[Code for this article is available on GitHub &lt;a href="https://github.com/JamesKovacs/NH3Features/tree/01-Loquacious"&gt;here&lt;/a&gt;.]&lt;/p&gt;  &lt;p&gt;One of the new features in NHibernate 3 is the addition of a fluent API for configuring NHibernate through code. Fluent NHibernate has provided a fluent configuration API for awhile, but now we have an option built into NHibernate itself. (Personally I prefer the new Loquacious API to Fluent NHibernate’s configuration API as I find Loquacious more discoverable. Given that Fluent NHibernate is built on top of NHibernate, you can always use Loquacious with Fluent NHibernate too. N.B. I still really like Fluent NHibernate’s ClassMap&amp;lt;T&amp;gt;, automapping capabilities, and PersistenceSpecification&amp;lt;T&amp;gt;. So don’t take my preference regarding fluent configuration as a denouncement of Fluent NHibernate.)&lt;/p&gt;  &lt;p&gt;The fluent configuration API built into NHibernate is called Loquacious configuration and exists as a set of extensions methods on NHibernate.Cfg.Configuration. You can access these extension methods by importing in the NHibernate.Cfg.Loquacious namespace.&lt;/p&gt;  &lt;pre&gt;var cfg = new Configuration();
cfg.Proxy(p =&amp;gt; p.ProxyFactoryFactory&amp;lt;ProxyFactoryFactory&amp;gt;())
   .DataBaseIntegration(db =&amp;gt; {
                            db.ConnectionStringName = &amp;quot;scratch&amp;quot;;
                            db.Dialect&amp;lt;MsSql2008Dialect&amp;gt;();
                            db.BatchSize = 500;
                        })
   .AddAssembly(typeof(Blog).Assembly)
   .SessionFactory().GenerateStatistics();&lt;/pre&gt;

&lt;p&gt;On the second line, we configure the ProxyFactoryFactory, which is responsible for generating the proxies needed for lazy loading. The ProxyFactoryFactory type parameter (stuff between the &amp;lt;&amp;gt;) is in the NHibernate.ByteCode.Castle namespace. (I have a reference to the NHibernate.ByteCode.Castle assembly too.) So we’re using Castle to generate our proxies. We could also use LinFu or Spring.&lt;/p&gt;

&lt;p&gt;Setting db.ConnectionStringName causes NHibernate to read the connection string from the &amp;lt;connectionStrings/&amp;gt; config section of the [App|Web].config. This keeps your connection strings in an easily managed location without being baked into your code. You can perform the same trick in XML-based configuration by using the &lt;em&gt;connection.connection_string_name&lt;/em&gt; property instead of the more commonly used &lt;em&gt;connection.connection_string&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Configuring BatchSize turns on update batching in databases, which support it. (Support is limited to SqlClient and OracleDataClient currently and relies on features of these drivers.) Updating batching allows NHibernate to group together multiple, related INSERT, UPDATE, or DELETE statements in a single round-trip to the database. This setting isn’t strictly necessary, but can give you a nice performance boost with DML statements. The value of 500 represents the maximum number of DML statements in one batch. The choice of 500 is arbitrary and should be tuned for your application.&lt;/p&gt;

&lt;p&gt;The assembly that we are adding is the one that contains our hbm.xml files as embedded resources. This allows NHibernate to find and parse our mapping metadata. If you have your metadata located in multiple files, you can call cfg.AddAssembly() multiple times.&lt;/p&gt;

&lt;p&gt;The last call, cfg.SessionFactory().GenerateStatistics(), causes NHibernate to output additional information about entities, collections, connections, transactions, sessions, second-level cache, and more. Although not required, it does provide additional useful information about NHibernate’s performance.&lt;/p&gt;

&lt;p&gt;Notice that there is no need to call &lt;em&gt;cfg.Configure()&lt;/em&gt;. cfg.Configure() is used to read in configuration values from [App|Web].config (from the hibernate-configuration config section) or from hibernate.cfg.xml. If we’ve not using XML configuration, cfg.Configure() is not required.&lt;/p&gt;

&lt;p&gt;Loquacious and XML-based configuration are not mutually exclusive. We can combine the two techniques to allow overrides or provide default values – it all comes down to the order of the Loquacious configuration code and the call to cfg.Configure().&lt;/p&gt;

&lt;pre&gt;var cfg = new Configuration();
cfg.Configure();
cfg.Proxy(p =&amp;gt; p.ProxyFactoryFactory&amp;lt;ProxyFactoryFactory&amp;gt;())
   .SessionFactory().GenerateStatistics();&lt;/pre&gt;

&lt;p&gt;Note the cfg.Configure() on the second line. We read in the standard XML-based configuration and then force the use of a particular ProxyFactoryFactory and generation of statistics via Loquacious configuration.&lt;/p&gt;

&lt;p&gt;If instead we make the call to cfg.Configure() after the Loquacious configuration, the Loquacious configuration provides default values, but we can override any and all values using XML-based configuration.&lt;/p&gt;

&lt;pre&gt;var cfg = new Configuration();
cfg.Proxy(p =&amp;gt; p.ProxyFactoryFactory&amp;lt;ProxyFactoryFactory&amp;gt;())
   .DataBaseIntegration(db =&amp;gt; {
                            db.ConnectionStringName = &amp;quot;scratch&amp;quot;;
                            db.Dialect&amp;lt;MsSql2008Dialect&amp;gt;();
                            db.BatchSize = 500;
                        })
   .AddAssembly(typeof(Blog).Assembly)
   .SessionFactory().GenerateStatistics();
cfg.Configure();&lt;/pre&gt;

&lt;p&gt;You can always mix and match the techniques by doing some Loquacious configuration before and som after the call to cfg.Configure().&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: If you call cfg.Configure(), you need to have &amp;lt;hibernate-configuration/&amp;gt; in your [App|Web].config or a hibernate.cfg.xml file. If you don’t, you’ll throw a HibernateConfigException. They can contain an empty root element, but it needs to be there. Another option would be to check whether File.Exists(‘hibernate.cfg.xml’) before calling cfg.Configure().&lt;/p&gt;

&lt;p&gt;So there you have it. The new Loquacious configuration API in NHibernate 3. This introduction was not meant as a definitive reference, but as a jumping off point. I would recommend that you explore other extension methods in the NHibernate.Cfg.Loquacious namespace as they provide the means to configure the 2nd-leve cache, current session context, custom LINQ functions, and more. Anything you can do in XML-based configuration can now be accomplished with Loquacious or the existing methods on NHibernate.Cfg.Configuration. So get out there and start coding – XML is now optional…&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=770" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2011%2F01%2F21%2Floquacious-configuration-in-nhibernate-3.aspx" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/gEWGJL4ArgE" height="1" width="1"&gt;</summary><author><name>James Kovacs</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1278345887768"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:655">tag:google.com,2005:reader/item/5478a5dc2e2f9112</id><title type="html">NHibernate Auditing v3 – Poor Man’s Envers</title><published>2010-07-05T13:30:00Z</published><updated>2010-07-05T13:30:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/VZkEp-A3K5E/nhibernate-auditing-v3-poor-man-s-envers.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2010/07/05/nhibernate-auditing-v3-poor-man-s-envers.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;First, let me explain the title of this post. The Hibernate folks – you know, that &lt;a href="http://nhforge.org"&gt;NHibernate&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Well, Simon Duduica is porting this over to .NET and NHibernate, and he’s making some AMAZING progress and on June 28th, shared this news with us on the NH Contrib development group:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi everybody,&lt;/p&gt;
&lt;p&gt;I have news regarding Envers.NET. I&amp;#39;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 :)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;So, on to the topic of this post. For &lt;span style="text-decoration:underline"&gt;NHibernate 3.0 Cookbook&lt;/span&gt;, I’ve included a section that explains how to use NHibernate to generate audit triggers. Originally, I had planned to use the code from &lt;a href="http://jasondentler.com/blog/2009/12/generate-audit-triggers-from-nhibernate-v2/"&gt;my previous blog post on the topic&lt;/a&gt;, 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 &lt;a href="http://code.google.com/p/unhaddins/"&gt;uNHAddIns&lt;/a&gt;. The “how-to use it” is explained in the book, so I won’t explain it here.&lt;/p&gt;
&lt;p&gt;Today, I was writing an integration test for this contribution, and thought the idea was worth sharing. I have a simple Cat class:&lt;/p&gt;
&lt;p&gt;&lt;img height="143" width="163" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram1.png" alt="ClassDiagram1" border="0" title="ClassDiagram1" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px"&gt; &lt;/p&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jasondentler.com/blog/wp-content/uploads/2010/07/image.png"&gt;&lt;img height="159" width="206" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/image_thumb.png" alt="image" border="0" title="image" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram11.png"&gt;&lt;img height="240" width="150" src="http://jasondentler.com/blog/wp-content/uploads/2010/07/ClassDiagram1_thumb.png" alt="ClassDiagram1" border="0" title="ClassDiagram1" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Next, I mapped it, made it readonly and excluded it from hbm2ddl with this mapping:&lt;/p&gt;
&lt;pre&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;hibernate-mapping xmlns=&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;
				   assembly=&amp;quot;uNhAddIns.Test&amp;quot;
				   namespace=&amp;quot;uNhAddIns.Test.Audit.TriggerGenerator&amp;quot;&amp;gt;
  &amp;lt;typedef class=&amp;quot;NHibernate.Type.EnumStringType`1[[uNhAddIns.Audit.TriggerGenerator.TriggerActions, uNhAddIns]], NHibernate&amp;quot;
           name=&amp;quot;triggerActions&amp;quot; /&amp;gt;
  &amp;lt;class name=&amp;quot;CatAudit&amp;quot; 
         mutable=&amp;quot;false&amp;quot;
         schema-action=&amp;quot;none&amp;quot;&amp;gt;
    &amp;lt;composite-id&amp;gt;
      &amp;lt;key-property name=&amp;quot;Id&amp;quot; /&amp;gt;
      &amp;lt;key-property name=&amp;quot;AuditUser&amp;quot; /&amp;gt;
      &amp;lt;key-property name=&amp;quot;AuditTimestamp&amp;quot; /&amp;gt;
    &amp;lt;/composite-id&amp;gt;
    &amp;lt;property name=&amp;quot;Color&amp;quot;/&amp;gt;
    &amp;lt;property name=&amp;quot;AuditOperation&amp;quot; type=&amp;quot;triggerActions&amp;quot; /&amp;gt;
  &amp;lt;/class&amp;gt;
	
&amp;lt;/hibernate-mapping&amp;gt;&lt;/pre&gt;
&lt;p&gt;I made it readonly by setting mutable=&amp;quot;false&amp;quot; and excluded it from hbm2ddl with schema-action=&amp;quot;none&amp;quot;. Thanks it!&lt;/p&gt;
&lt;p&gt;By the way, the &amp;lt;typedef&amp;gt; along with type=&amp;quot;triggerActions&amp;quot; just tells NHibernate I&amp;#39;ve stored my TriggerActions enum values as strings, not numbers.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=655" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2010%2F07%2F05%2Fnhibernate-auditing-v3-poor-man-s-envers.aspx" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/VZkEp-A3K5E" height="1" width="1"&gt;</summary><author><name>Jason Dentler</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1278157408414"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:652">tag:google.com,2005:reader/item/f566eb9bca99d916</id><category term="SessionFactory" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/SessionFactory/default.aspx" /><category term="BuildSessionFactory" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/BuildSessionFactory/default.aspx" /><category term="configuration" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/configuration/default.aspx" /><category term="Inversion of Control" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Inversion+of+Control/default.aspx" /><category term="IoC" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/IoC/default.aspx" /><category term="Unit of Work" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Unit+of+Work/default.aspx" /><category term="Asp.Net" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Asp.Net/default.aspx" /><category term="examples" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/examples/default.aspx" /><category term="quickstart" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/quickstart/default.aspx" /><category term="ASP.NET MVC" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/ASP.NET+MVC/default.aspx" /><title type="html">NHibernate Session Per Request Best Practices</title><published>2010-07-01T14:58:00Z</published><updated>2010-07-01T14:58:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/bR8RTOh6Up8/nhibernate-session-per-request-best-practices.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2010/07/01/nhibernate-session-per-request-best-practices.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;NHibernate used &amp;quot;nadav s&amp;quot; has provided a &lt;a href="http://nhforge.org/media/p/653.aspx"&gt;starter framework&lt;/a&gt; that shows a recommend means of starting NHibernate in Web Application. This makes use of IHttpModule to start an NHibernate UnitOfWork and then make sure the UnitOfWork is properly completed. This UnitOfWork checks to see if a transaction is active before ending the request and then cleans up that transaction.  It also uses an empty Inversion of Control container to allow further Separation of Concerns&lt;/p&gt;
&lt;p&gt;By using an IHttpModule rather than Global.asax the references to NHibernate are totally isolated so that they are external to the Web Application protion of the solution. This reduction in dependancies is desirable to ensure more reliable and maintainable code. The Web Application requires reference to the Framework project, where all the initialization code resides. The only initialization code not in the Framework project is the IHttpModule itself, which is in the Web Application project in the sample. However, even it could be placed in Framework project and still work correctly. The code for the IHttpModule is:&lt;/p&gt;
&lt;pre&gt;using System;&lt;br&gt;using System.Collections.Generic;&lt;br&gt;using System.Linq;&lt;br&gt;using System.Web;&lt;br&gt;using Framework;&lt;br&gt;
namespace SessionPerRequest&lt;br&gt;{&lt;br&gt;    public class UoWHttpModule : IHttpModule&lt;br&gt;    {&lt;br&gt;        public void Dispose()&lt;br&gt;        {&lt;br&gt;&lt;br&gt;   
        }&lt;br&gt;&lt;br&gt;        public void Init(HttpApplication context)&lt;br&gt;        {&lt;br&gt;            context.BeginRequest += new EventHandler(OnBeginRequest);&lt;br&gt;            context.EndRequest += new EventHandler(OnEndRequest);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;
        private void OnBeginRequest(object sender, EventArgs e)&lt;br&gt;        {&lt;br&gt;            IUoW uow = IoCContainer.Get&amp;lt;iuowprovider&amp;gt;().Current;&lt;br&gt;            uow.Init();&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        private void OnEndRequest(object sender, EventArgs e)&lt;br&gt;        {&lt;br&gt;            IUoW uow = IoCContainer.Get&amp;lt;iuowprovider&amp;gt;().Current;&lt;br&gt;            uow.End();&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;The OnBeginRequest or OnEndRequest need an IUoW object that is retrieved from WebUoWProvider class:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;&lt;br&gt;    internal class WebUoWProvider : IUoWProvider&lt;br&gt;    {&lt;br&gt;&lt;br&gt;        public IUoW Current&lt;br&gt;        {&lt;br&gt;            get&lt;br&gt;            {&lt;br&gt;                WebUoW uow = null;&lt;br&gt;                if (HttpContext.Current.Items[&amp;quot;uow&amp;quot;] == null)&lt;br&gt;                {   &lt;br&gt;                    uow = new WebUoW();&lt;br&gt;                    HttpContext.Current.Items[&amp;quot;uow&amp;quot;] = uow;&lt;br&gt;                }&lt;br&gt;                else&lt;br&gt;                {&lt;br&gt;                    uow = HttpContext.Current.Items[&amp;quot;uow&amp;quot;] as WebUoW;&lt;br&gt;                }&lt;br&gt;&lt;br&gt;                return uow;&lt;br&gt;            }&lt;br&gt;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;    }&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;The WebUoWProvider returns a WebUoW class that implements the IUoW interface. The WebUoW class is a wrapper for an NHUoW class that also implements the IUoW interface. First, here is the WebUoW code:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;    internal class WebUoW : IUoW&lt;br&gt;    {&lt;br&gt;        private NHUoW NHUoW;&lt;br&gt;&lt;br&gt;        public void Init()&lt;br&gt;        {&lt;br&gt;            this.NHUoW = new NHUoW();&lt;br&gt;            this.NHUoW.Init();&lt;br&gt;            HttpContext.Current.Items[&amp;quot;uow&amp;quot;] = this;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        public void End()&lt;br&gt;        {&lt;br&gt;            this.NHUoW.End();&lt;br&gt;            HttpContext.Current.Items[&amp;quot;uow&amp;quot;] = null;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        public void Attach(Entity entity)&lt;br&gt;        {&lt;br&gt;            this.NHUoW.Attach(entity);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;    }&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;And then the NHUoW class code:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;    internal class NHUoW : IUoW&lt;br&gt;    {&lt;br&gt;        protected virtual ISession Session { get; set; }&lt;br&gt;&lt;br&gt;        public void Init()&lt;br&gt;        {&lt;br&gt;            this.Session = SessionFactoryWrapper.Instance.OpenSession();&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        public void End()&lt;br&gt;        {&lt;br&gt;            if (this.Session != null)&lt;br&gt;            {&lt;br&gt;                if (this.Session.Transaction.IsActive)&lt;br&gt;                {&lt;br&gt;                    try&lt;br&gt;                    {&lt;br&gt;                        this.Session.Transaction.Commit();&lt;br&gt;                    }&lt;br&gt;                    catch (Exception ex)&lt;br&gt;                    {&lt;br&gt;                        this.Session.Transaction.Rollback();&lt;br&gt;                        IoCContainer.Get().LogError(ex);&lt;br&gt;                    }&lt;br&gt;&lt;br&gt;                    this.Session.Close();&lt;br&gt;                }&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        public void Attach(Entity entity)&lt;br&gt;        {&lt;br&gt;            this.Session.Lock(entity, LockMode.None);&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;
&lt;/pre&gt;
&lt;p&gt;The WebUoW class wraps an NHUoW class so that the same framework can be used for testing without having a Web Application running, as would be the case when using the NUnit console. The NHUoW class does a clean up if the Web Request ends before the application closes an active transaction. If the Web application were an exceptionally simple one it would be possible to put a BeginTransaction call in the NHUoW Init call.&lt;/p&gt;
&lt;p&gt;The sample solution from &amp;quot;nadav s&amp;quot; can be download from&lt;a href="http://nhforge.org/media/p/653.aspx"&gt; here&lt;/a&gt;. I will be using this as a starting point to complete a working solution for an NH3.0 sample application that will be described further in another blog.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=652" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2010%2F07%2F01%2Fnhibernate-session-per-request-best-practices.aspx" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/bR8RTOh6Up8" height="1" width="1"&gt;</summary><author><name>John Davidson</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1268070234386"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-4576066080975745098">tag:google.com,2005:reader/item/48f4577063609f36</id><category term="NHibernate" scheme="http://www.blogger.com/atom/ns#" /><category term="ConfORM" scheme="http://www.blogger.com/atom/ns#" /><category term="NH3" scheme="http://www.blogger.com/atom/ns#" /><title type="html">NHibernate: Mappings path</title><published>2010-03-03T03:29:00Z</published><updated>2010-03-03T03:30:19Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2010/03/nhibernate-mappings-path.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/4576066080975745098/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2010/03/nhibernate-mappings-path.html#comment-form" title="8 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">In the last Alt.NET café, about ConfORM, I noticed a confusion about NHibernate’s mappings management.  The image below show a simplified schema of the “mapping process”, the entry-point of some frameworks and the entry point of my examples :     This schema is working since NHibernate 2.0.0GA (2008-08-23)  Between NH2.0.0 and the actual trunk, what we have done is transform the usage of &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2010%2F03%2Fnhibernate-mappings-path.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=p7kpooEnD0o:qxuT7E0H3Kk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1262732683676"><id gr:original-id="http://ayende.com/Blog/archive/2010/01/05/nhibernate-vs.-entity-framework-4.0.aspx">tag:google.com,2005:reader/item/96d6ce8084fc8df9</id><category term="O/R Mappers" /><title type="html">NHibernate vs. Entity Framework 4.0</title><published>2010-01-05T10:00:00Z</published><updated>2010-01-05T10:00:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/AyendeRahien/~3/mUCeogic2cw/nhibernate-vs.-entity-framework-4.0.aspx" type="text/html" /><link rel="canonical" href="http://ayende.com/Blog/archive/2010/01/05/nhibernate-vs.-entity-framework-4.0.aspx" /><summary xml:base="http://ayende.com/blog/" type="html">&lt;p&gt;This is a question that I get &lt;em&gt;very&lt;/em&gt; frequently, and I always tried to dodged the bullet, but I get it so much that I feel that I have to provide an answer. Obviously, I am (not so) slightly biased toward NHibernate, so while you read it, please keep it in mind.&lt;/p&gt;  &lt;p&gt;EF 4.0 has done a lot to handle the issues that were raised with the previous version of EF. Thinks like transparent lazy loading, POCO classes, code only, etc. EF 4.0 is a much nicer than EF 1.0. &lt;/p&gt;  &lt;p&gt;The problem is that it is still a very young product, and the changes that were added only touched the surface. I already &lt;a href="http://ayende.com/Blog/archive/2009/05/29/why-defer-loading-in-entity-framework-isnrsquot-going-to-work.aspx"&gt;talked about some of my problems with the POCO model in EF&lt;/a&gt;, so I won’t repeat that, or &lt;a href="http://ayende.com/Blog/archive/2009/10/14/what-is-up-with-the-entity-framework-vnext.aspx"&gt;my reservations with the Code Only model&lt;/a&gt;. But basically, the major problem that I have with those two is that there seems to be a wall between what experience of the community and what Microsoft is doing. Both of those features shows much of the same issues that we have run into with NHibernate and Fluent NHibernate. Issues that were addressed and resolved, but show up in the EF implementations.&lt;/p&gt;  &lt;p&gt;Nevertheless, even ignoring my reservations about those, there are other indications that NHibernate’s maturity makes itself known. I run into that several times while I was writing the guidance for &lt;a href="http://efprof.com"&gt;EF Prof&lt;/a&gt;, there are things that you simple can’t do with EF, that are a natural part of NHibernate.&lt;/p&gt;  &lt;p&gt;I am &lt;em&gt;not&lt;/em&gt; going to try to do a point by point list of the differences, but it is interesting to look where we do find major differences between the capabilities of NHibernate and EF 4.0. Most of the time, it is in the ability to fine tune what the framework is actually doing. Usually, this is there to allow you to gain better performance from the system without sacrificing the benefits of using an OR/M in the first place.&lt;/p&gt;  &lt;p&gt;Here is a small list:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Write batching – NHibernate can be configured to batch all writes to the database so that when you need to write several statements to the database, NHibernate will only make a single round trip, instead of going to the database per each statement. &lt;/li&gt;    &lt;li&gt;Read batching / multi queries / futures – NHibernate allows to batch several queries into a single round trip to the database, instead of separate roundtrip per each query. &lt;/li&gt;    &lt;li&gt;Batched collection loads – When you lazy load a collection, NHibernate can find other collections of the same type that weren’t loaded, and load all of them in a single trip to the database. This is a great way to avoid having to deal with SELECT N+1. &lt;/li&gt;    &lt;li&gt;Collection with lazy=”extra” – Lazy extra means that NHibernate adapts to the operations that you might run on top of your collections. That means that blog.Posts.Count will &lt;em&gt;not&lt;/em&gt; force a load of the entire collection, but rather would create a “select count(*) from Posts where BlogId = 1” statement, and that blog.Posts.Contains() will likewise result in a single query rather than paying the price of loading the entire collection to memory. &lt;/li&gt;    &lt;li&gt;Collection filters and paged collections  - this allows you to define additional filters (including paging!) on top of your entities collections, which means that you can easily page through the blog.Posts collection, and not have to load the entire thing into memory. &lt;/li&gt;    &lt;li&gt;2nd level cache – managing the cache is &lt;em&gt;complex&lt;/em&gt;, &lt;a href="http://ayende.com/Blog/archive/2009/04/24/nhibernate-2nd-level-cache.aspx"&gt;I touched on why this is important before&lt;/a&gt;, so I’ll skip if for now. &lt;/li&gt;    &lt;li&gt;Tweaking – this is something that is critical whenever you need something that is just a bit beyond what the framework provides. With NHibernate, in nearly all the cases, you have an extension point, with EF, you are completely and utterly blocked. &lt;/li&gt;    &lt;li&gt;Integration &amp;amp; Extensibility – NHibernate has a &lt;em&gt;lot&lt;/em&gt; of extension projects, such as NHibernate Search, NHibernate Validator, NHibernate Shards, etc. Such projects not only do not exists for EF, but they cannot be written, for the most part, because EF has no extension points to speak of.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;On the other side, however:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;EF 4.0 has a better Linq provider than the current NHibernate implementation. This is something being actively worked on and the NH 3.0 will fix this gap. &lt;/li&gt;    &lt;li&gt;EF is from Microsoft.&lt;/li&gt; &lt;/ul&gt;&lt;img src="http://ayende.com/Blog/aggbug/11268.aspx" width="1" height="1"&gt;&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/AYENDE/46C559AC2E3661641B4A90E5D303F71297224D84"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/AYENDE/46C559AC2E3661641B4A90E5D303F71297224D84"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/mUCeogic2cw" height="1" width="1"&gt;</summary><author><name>Ayende Rahien</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/AyendeRahien"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/AyendeRahien</id><title type="html">Ayende @ Rahien</title><link rel="alternate" href="http://ayende.com/blog/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1261343764989"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:566">tag:google.com,2005:reader/item/df084a78e2e1ea2e</id><title type="html">QueryOver in NH 3.0</title><published>2009-12-17T23:22:00Z</published><updated>2009-12-17T23:22:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/HbveCVb-ock/queryover-in-nh-3-0.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;h4&gt;&lt;a name="Introduction"&gt;&lt;/a&gt;Introduction&lt;/h4&gt;
&lt;p&gt;
    The ICriteria API
    is NHibernate&amp;#39;s implementation of &lt;a href="http://martinfowler.com/eaaCatalog/queryObject.html"&gt;Query Object&lt;/a&gt;.
    NHibernate 3.0 introduces the QueryOver api, which combines the use of
    &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx"&gt;Extension Methods&lt;/a&gt;
    and
    &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx"&gt;Lambda Expressions&lt;/a&gt;
    (both new in .Net 3.5) to provide a statically typesafe wrapper round the ICriteria API.
&lt;/p&gt;
&lt;p&gt;
    QueryOver uses Lambda Expressions to provide some extra
    syntax to remove the &amp;#39;magic strings&amp;#39; from your ICriteria queries.
&lt;/p&gt;
&lt;p&gt;
    So, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.Add(Expression.Eq(&amp;quot;Name&amp;quot;, &amp;quot;Smith&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;becomes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.Where&amp;lt;Person&amp;gt;(p =&amp;gt; p.Name == &amp;quot;Smith&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    With this kind of syntax there are no &amp;#39;magic strings&amp;#39;, and refactoring tools like
    &amp;#39;Find All References&amp;#39;, and &amp;#39;Refactor-&amp;gt;Rename&amp;#39; work perfectly.
&lt;/p&gt;
&lt;p&gt;
    Note: QueryOver is intended to remove the references to &amp;#39;magic strings&amp;#39;
    from the ICriteria API while maintaining it&amp;#39;s opaqueness.  It is &lt;span style="text-decoration:underline"&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/span&gt; a LINQ provider;
    NHibernate 3.0 has a built-in Linq provider for this.
&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="StructureOfAQuery"&gt;&lt;/a&gt;Structure of a Query&lt;/h4&gt;
&lt;p&gt;
    Queries are created from an ISession using the syntax:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList&amp;lt;Cat&amp;gt; cats =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Where(c =&amp;gt; c.Name == &amp;quot;Max&amp;quot;)
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Detached QueryOver (analagous to DetachedCriteria) can be created, and then used with an ISession using:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QueryOver&amp;lt;Cat&amp;gt; query =
    QueryOver.Of&amp;lt;Cat&amp;gt;()
        .Where(c =&amp;gt; c.Name == &amp;quot;Paddy&amp;quot;);
        
IList&amp;lt;Cat&amp;gt; cats =
    query.GetExecutableQueryOver(session)
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Queries can be built up to use restrictions, projections, and ordering using
    a fluent inline syntax:    
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var catNames =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .WhereRestrictionOn(c =&amp;gt; c.Age).IsBetween(2).And(8)
        .Select(c =&amp;gt; c.Name)
        .OrderBy(c =&amp;gt; c.Name).Asc
        .List&amp;lt;string&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="SimpleExpressions"&gt;&lt;/a&gt;Simple Expressions&lt;/h4&gt;
&lt;p&gt;
    The Restrictions class (used by ICriteria) has been extended to include overloads
    that allow Lambda Expression syntax.  The Where() method works for simple expressions (&amp;lt;, &amp;lt;=, ==, !=, &amp;gt;, &amp;gt;=)
    so instead of:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ICriterion equalCriterion = Restrictions.Eq(&amp;quot;Name&amp;quot;, &amp;quot;Max&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    You can write:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ICriterion equalCriterion = Restrictions.Where&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Name == &amp;quot;Max&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Since the QueryOver class (and IQueryOver interface) is generic and knows the type of the query,
    there is an inline syntax for restrictions that does not require the additional qualification
    of class name.  So you can also write:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var cats =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Where(c =&amp;gt; c.Name == &amp;quot;Max&amp;quot;)
        .And(c =&amp;gt; c.Age &amp;gt; 4)
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Note, the methods Where() and And() are semantically identical; the And() method is purely to allow
    QueryOver to look similar to HQL/SQL.
&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Boolean comparisons can be made directly instead of comparing to true/false:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Where(p =&amp;gt; p.IsParent)
        .And(p =&amp;gt; !p.IsRetired)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Simple expressions can also be combined using the || and &amp;amp;&amp;amp; operators.  So ICriteria like:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Add(Restrictions.And(
            Restrictions.Eq(&amp;quot;Name&amp;quot;, &amp;quot;test name&amp;quot;),
            Restrictions.Or(
                Restrictions.Gt(&amp;quot;Age&amp;quot;, 21),
                Restrictions.Eq(&amp;quot;HasCar&amp;quot;, true))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Can be written in QueryOver as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Where(p =&amp;gt; p.Name == &amp;quot;test name&amp;quot; &amp;amp;&amp;amp; (p.Age &amp;gt; 21 || p.HasCar))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Each of the corresponding overloads in the QueryOver API allows the use of regular ICriterion
    to allow access to private properties.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Where(Restrictions.Eq(&amp;quot;Name&amp;quot;, &amp;quot;Max&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    It is worth noting that the QueryOver API is built on top of the ICriteria API.  Internally the structures are the same, so at runtime
    the statement below, and the statement above, are stored as exactly the same ICriterion.  The actual Lambda Expression is not stored
    in the query.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Where(c =&amp;gt; c.Name == &amp;quot;Max&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="AdditionalRestrictions"&gt;&lt;/a&gt;Additional Restrictions&lt;/h4&gt;
&lt;p&gt;
    Some SQL operators/functions do not have a direct equivalent in C#.
    (e.g., the SQL &lt;code&gt;where name like &amp;#39;%anna%&amp;#39;&lt;/code&gt;).
    These operators have overloads for QueryOver in the Restrictions class, so you can write:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Where(Restrictions.On&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Name).IsLike(&amp;quot;%anna%&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    There is also an inline syntax to avoid the qualification of the type:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .WhereRestrictionOn(c =&amp;gt; c.Name).IsLike(&amp;quot;%anna%&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    While simple expressions (see above) can be combined using the || and &amp;amp;&amp;amp; operators, this is not possible with the other
    restrictions.  So this ICriteria:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Add(Restrictions.Or(
            Restrictions.Gt(&amp;quot;Age&amp;quot;, 5)
            Restrictions.In(&amp;quot;Name&amp;quot;, new string[] { &amp;quot;Max&amp;quot;, &amp;quot;Paddy&amp;quot; })))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Would have to be written as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        .Add(Restrictions.Or(
            Restrictions.Where&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Age &amp;gt; 5)
            Restrictions.On&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Name).IsIn(new string[] { &amp;quot;Max&amp;quot;, &amp;quot;Paddy&amp;quot; })))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="Associations"&gt;&lt;/a&gt;Associations&lt;/h4&gt;
&lt;p&gt;
    QueryOver can navigate association paths using JoinQueryOver() (analagous to ICriteria.CreateCriteria() to create sub-criteria).
&lt;/p&gt;
&lt;p&gt;
    The factory method QuerOver&amp;lt;T&amp;gt;() on ISession returns an IQueryOver&amp;lt;T&amp;gt;.
    More accurately, it returns an IQueryOver&amp;lt;T,T&amp;gt; (which inherits from IQueryOver&amp;lt;T&amp;gt;).
&lt;/p&gt;
&lt;p&gt;
    An IQueryOver has two types of interest; the root type (the type of entity that the query returns),
    and the type of the &amp;#39;current&amp;#39; entity being queried.  For example, the following query uses
    a join to create a sub-QueryOver (analagous to creating sub-criteria in the ICriteria API):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IQueryOver&amp;lt;Cat,Kitten&amp;gt; catQuery =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .JoinQueryOver(c =&amp;gt; c.Kittens)
            .Where(k =&amp;gt; k.Name == &amp;quot;Tiddles&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    The JoinQueryOver returns a new instance of the IQueryOver than has its root at the Kittens collection.
    The default type for restrictions is now Kitten (restricting on the name &amp;#39;Tiddles&amp;#39; in the above example),
    while calling .List() will return an IList&amp;lt;Cat&amp;gt;.  The type IQueryOver&amp;lt;Cat,Kitten&amp;gt; inherits from IQueryOver&amp;lt;Cat&amp;gt;.
&lt;/p&gt;
&lt;p&gt;
    Note, the overload for JoinQueryOver takes an IEnumerable&amp;lt;T&amp;gt;, and the C# compiler infers the type from that.
    If your collection type is not IEnumerable&amp;lt;T&amp;gt;, then you need to qualify the type of the sub-criteria:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IQueryOver&amp;lt;Cat,Kitten&amp;gt; catQuery =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .JoinQueryOver&lt;span style="text-decoration:underline"&gt;&amp;lt;Kitten&amp;gt;&lt;/span&gt;(c =&amp;gt; c.Kittens)
            .Where(k =&amp;gt; k.Name == &amp;quot;Tiddles&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    The default join is an inner-join.  Each of the additional join types can be specified using
    the methods &lt;code&gt;.Inner, .Left, .Right,&lt;/code&gt; or &lt;code&gt;.Full&lt;/code&gt;.
    For example, to left outer-join on Kittens use:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IQueryOver&amp;lt;Cat,Kitten&amp;gt; catQuery =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Left.JoinQueryOver(c =&amp;gt; c.Kittens)
            .Where(k =&amp;gt; k.Name == &amp;quot;Tiddles&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="Aliases"&gt;&lt;/a&gt;Aliases&lt;/h4&gt;
&lt;p&gt;
    In the traditional ICriteria interface aliases are assigned using &amp;#39;magic strings&amp;#39;, however their value
    does not correspond to a name in the object domain.  For example, when an alias is assigned using
    &lt;code&gt;.CreateAlias(&amp;quot;Kitten&amp;quot;, &amp;quot;kittenAlias&amp;quot;)&lt;/code&gt;, the string &amp;quot;kittenAlias&amp;quot; does not correspond
    to a property or class in the domain.
&lt;/p&gt;
&lt;p&gt;
    In QueryOver, aliases are assigned using an empty variable.
    The variable can be declared anywhere (but should
    be empty/default at runtime).  The compiler can then check the syntax against the variable is
    used correctly, but at runtime the variable is not evaluated (it&amp;#39;s just used as a placeholder for
    the alias).
&lt;/p&gt;
&lt;p&gt;
    Each Lambda Expression function in QueryOver has a corresponding overload to allow use of aliases,
    and a .JoinAlias function to traverse associations using aliases without creating a sub-QueryOver.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Cat catAlias = null;
Kitten kittenAlias = null;

IQueryOver&amp;lt;Cat,Cat&amp;gt; catQuery =
    session.QueryOver&amp;lt;Cat&amp;gt;(() =&amp;gt; catAlias)
        .JoinAlias(() =&amp;gt; catAlias.Kittens, () =&amp;gt; kittenAlias)
        .Where(() =&amp;gt; catAlias.Age &amp;gt; 5)
        .And(() =&amp;gt; kittenAlias.Name == &amp;quot;Tiddles&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;&lt;a name="Projections"&gt;&lt;/a&gt;Projections&lt;/h4&gt;
&lt;p&gt;
    Simple projections of the properties of the root type can be added using the &lt;code&gt;.Select&lt;/code&gt; method
    which can take multiple Lambda Expression arguments:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList selection =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Select(
            c =&amp;gt; c.Name,
            c =&amp;gt; c.Age)
        .List&amp;lt;object[]&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Because this query no longer returns a Cat, the return type must be explicitly specified.
    If a single property is projected, the return type can be specified using:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList&amp;lt;int&amp;gt; ages =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Select(c =&amp;gt; c.Age)
        .List&amp;lt;int&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    However, if multiple properties are projected, then the returned list will contain
    object arrays, as per a projection
    in ICriteria.  This could be fed into an anonymous type using:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var catDetails =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Select(
            c =&amp;gt; c.Name,
            c =&amp;gt; c.Age)
        .List&amp;lt;object[]&amp;gt;()
        .Select(properties =&amp;gt; new {
            CatName = (string)properties[0],
            CatAge = (int)properties[1],
            });
            
Console.WriteLine(catDetails[0].CatName);
Console.WriteLine(catDetails[0].CatAge);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    Note that the second &lt;code&gt;.Select&lt;/code&gt; call in this example is an extension method on IEnumerable&amp;lt;T&amp;gt; supplied in System.Linq;
    it is not part of NHibernate.
&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    QueryOver allows arbitrary IProjection to be added (allowing private properties to be projected).  The Projections factory
    class also has overloads to allow Lambda Expressions to be used:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList selection =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Select(Projections.ProjectionList()
            .Add(Projections.Property&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Name))
            .Add(Projections.Avg&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Age)))
        .List&amp;lt;object[]&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    In addition there is an inline syntax for creating projection lists that does not require the explicit class qualification:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList selection =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .SelectList(list =&amp;gt; list
            .Select(c =&amp;gt; c.Name)
            .SelectAvg(c =&amp;gt; c.Age))
        .List&amp;lt;object[]&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    Projections can also have arbitrary aliases assigned to them to allow result transformation.
    If there is a CatSummary DTO class defined as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class CatSummary
{
    public string Name { get; set; }
    public int AverageAge { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    ... then aliased projections can be used with the AliasToBean&amp;lt;T&amp;gt; transformer:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CatSummary summaryDto = null;
IList&amp;lt;CatSummary&amp;gt; catReport =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .SelectList(list =&amp;gt; list
            .SelectGroup(c =&amp;gt; c.Name).WithAlias(() =&amp;gt; summaryDto.Name)
            .SelectAvg(c =&amp;gt; c.Age).WithAlias(() =&amp;gt; summaryDto.AverageAge))
        .TransformUsing(Transformers.AliasToBean&amp;lt;CatSummary&amp;gt;())
        .List&amp;lt;CatSummary&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;&lt;a name="Subqueries"&gt;&lt;/a&gt;Subqueries&lt;/h4&gt;
&lt;p&gt;
    The Subqueries factory class has overloads to allow Lambda Expressions to express sub-query
    restrictions.  For example:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QueryOver&amp;lt;Cat&amp;gt; maximumAge =
    QueryOver.Of&amp;lt;Cat&amp;gt;()
        .SelectList(p =&amp;gt; p.SelectMax(c =&amp;gt; c.Age));

IList&amp;lt;Cat&amp;gt; oldestCats =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .Where(Subqueries.WhereProperty&amp;lt;Cat&amp;gt;(c =&amp;gt; c.Age).Eq(maximumAge))
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    The inline syntax allows you to use subqueries without requalifying the type:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList&amp;lt;Cat&amp;gt; oldestCats =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .WithSubquery.WhereProperty(c =&amp;gt; c.Age).Eq(maximumAge)
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;
    There is an extension method &lt;code&gt;As()&lt;/code&gt; on (a detached) QueryOver that allows you to cast it to any type.
    This is used in conjunction with the overloads &lt;code&gt;Where(), WhereAll(),&lt;/code&gt; and &lt;code&gt;WhereSome()&lt;/code&gt;
    to allow use of the built-in C# operators for comparison, so the above query can be written as:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IList&amp;lt;Cat&amp;gt; oldestCats =
    session.QueryOver&amp;lt;Cat&amp;gt;()
        .WithSubquery.Where(c =&amp;gt; c.Age == maximumAge.As&amp;lt;int&amp;gt;())
        .List();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=566" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2009%2F12%2F17%2Fqueryover-in-nh-3-0.aspx" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/HbveCVb-ock" height="1" width="1"&gt;</summary><author><name>Richard Brown</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1261085769644"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:561">tag:google.com,2005:reader/item/9312884d2f3cf2ef</id><category term="NHibernate" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/NHibernate/default.aspx" /><title type="html">Linq to NHibernate Progress Report - A Christmas Gift?</title><published>2009-12-17T00:00:00Z</published><updated>2009-12-17T00:00:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/i_8vDdqmJBs/linq-to-nhibernate-progress-report-a-christmas-gift.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2009/12/17/linq-to-nhibernate-progress-report-a-christmas-gift.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;Time for another progress report, and this one&amp;#39;s a biggie :)&lt;/p&gt;
&lt;p&gt;Barring a couple of pretty minor things that won&amp;#39;t take much fixing, all the original Linq tests have now been ported over to the new provider and are all passing. That means the new provider is now (from the perspective of the tests, at least) in better shape that the version 1 provider. It can do everything the original provider could, plus a whole bunch more. A couple of example queries that now work just fine are:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;  from e in db.Employees&lt;br&gt;
  from et in e.Territories&lt;br&gt;
  where e.Address.City == &amp;quot;Seattle&amp;quot;&lt;br&gt;
  select new {e.FirstName, e.LastName, et.Region.Description};&lt;br&gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;  from c in db.Customers&lt;br&gt;
  join o in db.Orders on c.CustomerId equals o.Customer.CustomerId into orders&lt;br&gt;
  select new {c.ContactName, OrderCount = orders.Average(x =&amp;gt; x.Freight)};&lt;br&gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;  from o in db.Orders&lt;br&gt;
  from p in db.Products&lt;br&gt;
  join d in db.OrderLines on new {o.OrderId, p.ProductId} equals new {d.Order.OrderId, d.Product.ProductId}&lt;br&gt;
   into details&lt;br&gt;
  from d in details&lt;br&gt;
  select new {o.OrderId, p.ProductId, d.UnitPrice}&lt;br&gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;  from c in db.Customers&lt;br&gt;
  join o in db.Orders on c.CustomerId equals o.Customer.CustomerId&lt;br&gt;
  group o by c into x&lt;br&gt;
  select new { CustomerName = x.Key.ContactName, Order = x }&lt;br&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(ignore whether those queries make any real sense, it&amp;#39;s just the form of them that matters)&lt;/p&gt;
&lt;p&gt;So, more importantly, what doesn&amp;#39;t work? Well, out of the tests that we&amp;#39;ve currently got, not a huge amount. Some important areas that are missing are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nested selects to produce hierarchical output. I&amp;#39;ve got some prototype code for doing this, so it will be supported at some point but isn&amp;#39;t there right now. Of course, since NH already understands relationships, nested selects are far less important than they are for something like Linq to SQL.&lt;/li&gt;
&lt;li style="list-style:none"&gt;&lt;/li&gt;
&lt;li&gt;Group joins that produce hierarchical output - these essentially boil down to the same code as the nested select case, so support for these will probably come at around the same time. Group joins that don&amp;#39;t introduce a hierarchy should work just fine.&lt;/li&gt;
&lt;li style="list-style:none"&gt;&lt;/li&gt;
&lt;li&gt;Set operations, such as Union and Intersect. Union you can obviously do yourself in client code with no particular overhead. Intersect would really be better in the provider :)&lt;/li&gt;
&lt;li style="list-style:none"&gt;&lt;/li&gt;
&lt;li&gt;Left outer join style queries, such as:&lt;br&gt;
  &lt;br&gt;
  &lt;code&gt;from e in db.Employees&lt;br&gt;
  join o in db.Orders on e equals o.Employee into ords&lt;br&gt;
  from o in ords.DefaultIfEmpty()&lt;br&gt;
  select new {e.FirstName, e.LastName, Order = o};&lt;br&gt;
  &lt;br&gt;&lt;/code&gt; This is a fairly widely used construct, so is close to top of the list for future support&lt;/li&gt;
&lt;li style="list-style:none"&gt;&lt;/li&gt;
&lt;li&gt;Let expressions, such as:&lt;br&gt;
  &lt;br&gt;
  &lt;code&gt;from c in db.Customers&lt;br&gt;
  join o in db.Orders on c.CustomerId equals o.Customer.CustomerId into ords&lt;br&gt;
  let z = c.Address.City + c.Address.Country&lt;br&gt;
  from o in ords&lt;br&gt;
  select new {c.ContactName, o.OrderId, z};&lt;br&gt;
  &lt;br&gt;&lt;/code&gt; Again, this is quite high on the TODO list.&lt;/li&gt;
&lt;li style="list-style:none"&gt;&lt;/li&gt;
&lt;li&gt;Support for custom functions. This is actually fully implemented internally, but I just want to review the API usage before I tell you all how to use it - it probably needs a little cleanup from it&amp;#39;s current state, but I don&amp;#39;t anticipate any major changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#39;ve also got a number of TODOs, but mainly cleanup rather than functional, plus I need to work through the error handling to ensure that any queries that are passed in that the provider &lt;strong&gt;can&amp;#39;t&lt;/strong&gt; handle are rejected gracefully rather than just barfing (which is the likely case right now).&lt;/p&gt;
&lt;p&gt;The only gotcha that I know of is a query that runs just fine but doesn&amp;#39;t necessarily return the correct number of results. Specifically, queries like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;  from user in db.Users&lt;br&gt;
  select new&lt;br&gt;
  {&lt;br&gt;
    user.Name,&lt;br&gt;
    RoleName = user.Role.Name&lt;br&gt;
  };&lt;br&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Right now, this generates a &lt;strong&gt;join&lt;/strong&gt; to the Role table, so any users that &lt;strong&gt;don&amp;#39;t&lt;/strong&gt; have a role are not returned. This differs from Linq to SQL where a &lt;strong&gt;left join&lt;/strong&gt; is generated, giving a null RoleName for any users without a role. I believe the Linq to SQL implementation to be correct - the above query doesn&amp;#39;t explicitly have any form of filtering (where clause, join clause etc), so you should get back all the users in the database. This one is top of the list, and hopefully will be fixed soon (it&amp;#39;s not hard, I&amp;#39;ve just run out of time!).&lt;/p&gt;
&lt;p&gt;In summary, I&amp;#39;m getting pretty happy with the state of the provider and think that it&amp;#39;s now ready for general usage - although there are still some important query forms to support, I think there&amp;#39;s sufficient there now to do useful work. If you&amp;#39;ve got good test coverage, then I&amp;#39;d even be happy for it to go live. If you don&amp;#39;t have good coverage, then don&amp;#39;t come crying to me :)&lt;/p&gt;
&lt;p&gt;Of course, this is all in the trunk, so anyone wanting to play either needs to get the trunk source and build it, or take the much easier option of having &lt;a href="http://www.hornget.net/packages/orm/nhibernate/nhibernate-trunk"&gt;Horn&lt;/a&gt; do the work. Horn builds the trunk on a daily basis, so look for a package built after around 2300GMT on the 16/12/2009 (the package URL on Horn has the datetime stamp in it, so it&amp;#39;s pretty easy to spot).&lt;/p&gt;
&lt;p&gt;I&amp;#39;m on holiday for the next couple of weeks, and will only have intermittent internet access. However, ping me either by email or twitter with comments / bugs / suggestions, and I&amp;#39;ll do my best to reply. Normal service (whatever that is) will return around Jan 4th.&lt;/p&gt;
&lt;div&gt;&lt;a rel="tag" href="http://technorati.com/tag/Linq"&gt;Linq&lt;/a&gt;, &lt;a rel="tag" href="http://technorati.com/tag/NHibernate"&gt;NHibernate&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=561" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/468/60#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2009%2F12%2F17%2Flinq-to-nhibernate-progress-report-a-christmas-gift.aspx" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/i_8vDdqmJBs" height="1" width="1"&gt;</summary><author><name>Steve Strong</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1260264818213"><id gr:original-id="2a2e7ade-7474-448b-9de5-1515d8bb7d1b:162126">tag:google.com,2005:reader/item/f9f578450eb02f70</id><category term="patrones diseño ORM herencia arquitectura" scheme="http://geeks.ms/blogs/omarvr/archive/tags/patrones+dise_26002300_241_3B00_o+ORM+herencia+arquitectura/default.aspx" /><title type="html">La herencia mal planteada</title><published>2009-12-07T21:55:00Z</published><updated>2009-12-07T21:55:00Z</updated><link rel="alternate" href="http://geeks.ms/blogs/omarvr/archive/2009/12/07/la-herencia-mal-planteada.aspx" type="text/html" /><summary xml:base="http://geeks.ms/blogs/" type="html">&lt;p&gt;&lt;span&gt;En cuestiones de &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM (Object Relational Mapping)&lt;/a&gt; casi siempre asociamos una relación uno a uno (1:1) en bases de datos relacionales, con una herencia de clases. Esquematizar este tipo de diseño puede llevarnos a futuros errores cuando nos planteamos la arquitectura de cualquier proyecto.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Vamos a ver ejemplos que nos permitan entender dónde está la trampa.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Si tratamos de representar la estructura de mascotas en un diagrama de clases, pudiéramos pensar que todas tienen un dueño, al igual que todas tienen un nombre y una fecha de nacimiento. De ahí, y derivando en acciones más específicas, vemos que algunas mascotas se pueden acariciar (perro, gato), y otras no tanto (por ejemplo una serpiente, sí sí, una serpiente, que dueños locos se sobran en este mundo).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Representando esto, tendríamos una clase mascota, que tendría una propiedad persona (dueño), otra propiedad fecha de nacimiento, y todas aquellas que entendamos pueden ser comunes a todas las mascotas. &lt;/span&gt;&lt;span&gt;Luego, cada mascota, heredaría su funcionalidad e implementaría sus funciones más específicas (no quiero complicar el diagrama porque al final no es el objetivo de este artículo)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img height="443" width="438" src="http://omar-delvalle.sinportales.es/images/omar-delvalle_sinportales_es/mascotas(1).png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Este diagrama, traducido a una base de datos relacional, nos quedaría con tres tablas, mascota, perro y serpiente, donde tendríamos una relación de uno a uno entre ellas, y cualquier ORM decente, sabría que leer un perro implica leer la información asociada al mismo en la tabla mascota, y lo mismo ocurriría si tratamos de insertar o actualizar cualquiera de las clases que implementen mascota.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Pero…  (Siempre hay un pero)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Si analizamos esto mismo con alumnos y maestros, ¿qué pasaría? Vamos allá…&lt;/p&gt;
&lt;p&gt;Un maestro, al igual que un alumno, son personas, ambos tienen un nombre, apellidos, padres, edad, etc. Mientras más elementos en común tengan varias clase, más confirmamos la presencia de una herencia, así que si llevamos esto a un diagrama de clases, nos quedaría de la siguiente forma:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img height="367" width="526" src="http://omar-delvalle.sinportales.es/images/omar-delvalle_sinportales_es/personas.png" alt=""&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Visto desde el punto de vista de bases de datos, igual caeríamos en tres tablas, con una relación uno a uno entre ellas (persona, maestro y alumno) y todo perfecto con el ORM. Todo perfecto hasta que a un maestro se le ocurre estudiar. Plantearnos esta situación nos crea un problema, ¿cómo digo yo que un maestro también es un alumno? ¿Cómo puedo asumir que una misma persona ahora es estudiante y maestro? &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;La encapsulación de la propia herencia no lo permite, yo no podría reutilizar la información de persona ahora en alumno, por lo que aquí la herencia &lt;strong&gt;no aplica &lt;/strong&gt;y, la solución pasa por convertir la herencia, en &lt;strong&gt;una asociación&lt;/strong&gt; de Persona tanto en la clase Maestro como en la clase Alumno, o como una alternativa, pudiéramos definir una lista de responsabilidades asociadas a una persona, de manera que pudiera ocupar la función de alumno y maestro al mismo tiempo.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img height="342" width="485" src="http://omar-delvalle.sinportales.es/images/omar-delvalle_sinportales_es/personas_bien.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;¿Cómo podemos identificar este tipo de problema cuando nos enfrentamos a un diseño de cualquier aplicación? &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;Roles que definen responsabilidad&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Los roles son actividades que pueden ser compartidas por un elemento de nuestro diseño, siempre que exista un mismo objeto que pueda compartir más de un rol, la herencia no es la solución. Es por esto que en el análisis de mascotas esto no ocurre, ya que un perro no podrá ser nunca una serpiente y tampoco viceversa, al menos hasta hoy ;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Fabio Maulo, team leader de para mí el mejor ORM que existe hoy en día, NHibernate, hace mucho tiempo hacía una historia sobre &lt;a href="http://groups.google.com.ar/group/nhibernate-hispano/browse_thread/thread/cdb659fb02c264e0"&gt;un personaje que vive en las colinas de Italia&lt;/a&gt; y que ejemplificaba este problema con la herencia.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Salu2&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=162126" width="1" height="1"&gt;</summary><author><name>Omar del Valle Rodríguez</name></author><source gr:stream-id="feed/http://geeks.ms/blogs/mainfeed.aspx"><id>tag:google.com,2005:reader/feed/http://geeks.ms/blogs/mainfeed.aspx</id><title type="html">Geeks•ms</title><link rel="alternate" href="http://geeks.ms/blogs/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1258553345434"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-3811176229865047791">tag:google.com,2005:reader/item/06d51c94756a0e50</id><category term="Validator" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">NHibernate.Validator: Tags</title><published>2009-11-17T23:21:00Z</published><updated>2010-01-14T21:01:02Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/11/nhibernatevalidator-tags.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/3811176229865047791/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/11/nhibernatevalidator-tags.html#comment-form" title="5 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">At the begin of NHibernate Validator we have talked about the exigency of assign a “gravity level” to each validation (for instance Error, Warning, Information). In the last year we had requests for “validation grouping” and “different validation, for the same entity, in different contexts”. Our answer is: validation tagging What is a tag In NHibernate Validator a tag has de same meaning you are &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F11%2Fnhibernatevalidator-tags.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=F48d4D3731g:oAAzRvm-i-Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1256767288805"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-1531277984124609766">tag:google.com,2005:reader/item/08ce2e984982f44b</id><category term="Validator" scheme="http://www.blogger.com/atom/ns#" /><category term="Fluent-configuration" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">NHibernate.Validator : Customizing messages (Message Interpolator)</title><published>2009-10-28T10:00:00Z</published><updated>2009-10-28T10:00:16Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-customizing_28.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/1531277984124609766/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-customizing_28.html#comment-form" title="0 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">The message interpolator is the responsible of the messages translation/composition. In the coming soon version (NHV-1.2.0) we had increase its power (and refactorized its implementation).  Has default NHV has two implementations: DefaultMessageInterpolatorAggregator and DefaultMessageInterpolator.  What is the usual you have seen in NHibernate’s eco-system ?  Yes, you are right: Injectability!!!&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F10%2Fnhibernatevalidator-customizing_28.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=uL3ql7-DoAM:kOxoRSHBo08:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1256594707338"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:534">tag:google.com,2005:reader/item/3409cc680bc0aa6b</id><category term="validation" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/validation/default.aspx" /><category term="News" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/News/default.aspx" /><category term="Release" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Release/default.aspx" /><category term="Validator" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Validator/default.aspx" /><title type="html">NHibernate Validator 1.2 Beta3 released</title><published>2009-10-26T16:12:00Z</published><updated>2009-10-26T16:12:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/TguI2GnZnUc/nhibernate-validator-1-2-beta3-released.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2009/10/26/nhibernate-validator-1-2-beta3-released.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;&lt;img src="http://darioquintana.com.ar/files/NHV-logo-white-background.png" alt=""&gt;

&lt;/p&gt;
&lt;p&gt;Download NHibernate Validator 1.2 beta3 with sources, binaries and example here &lt;a href="https://sourceforge.net/projects/nhcontrib/files"&gt;here&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;For use it with NHibernate 2.1 GA.
&lt;/p&gt;
&lt;p&gt;For examples and documentation see the serie of blog posts of Fabio Maulo about NHibernate Validator &lt;a href="http://fabiomaulo.blogspot.com/search/label/Validator"&gt;here&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=534" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2009%2F10%2F26%2Fnhibernate-validator-1-2-beta3-released.aspx" width="100%" height="250" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/TguI2GnZnUc" height="1" width="1"&gt;</summary><author><name>Dario Quintana</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1256594686065"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-3205821911232617123">tag:google.com,2005:reader/item/89ff8f6e39b758b0</id><category term="Validator" scheme="http://www.blogger.com/atom/ns#" /><category term="Fluent-configuration" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">NHibernate.Validator : Extending ValidationDef</title><published>2009-10-26T08:00:00Z</published><updated>2009-10-26T12:14:22Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-extending_26.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/3205821911232617123/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-extending_26.html#comment-form" title="4 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">In various applications I’m using my implementation of Range.  public interface IRange&amp;lt;T&amp;gt; : IEquatable&amp;lt;IRange&amp;lt;T&amp;gt;&amp;gt; where T : IComparable&amp;lt;T&amp;gt;{T LowLimit { get; }T HighLimit { get; }bool IsEmpty { get; }bool Includes(T value);bool Includes(IRange&amp;lt;T&amp;gt; other);bool Overlaps(IRange&amp;lt;T&amp;gt; other);}As you can imagine I’m using it to represent various kind of ranges and in each usage I need to validate the range&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F10%2Fnhibernatevalidator-extending_26.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=m6Yd6UgaJL0:qOvgw2_Ab70:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1256384450894"><id gr:original-id="http://ayende.com/Blog/archive/2009/10/24/nhibernate-webcasts-series.aspx">tag:google.com,2005:reader/item/e96c694c6434d196</id><category term="NHibernate" /><title type="html">NHibernate webcasts series</title><published>2009-10-24T10:12:00Z</published><updated>2009-10-24T10:12:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/AyendeRahien/~3/ysJIEicpaKw/nhibernate-webcasts-series.aspx" type="text/html" /><link rel="canonical" href="http://ayende.com/Blog/archive/2009/10/24/nhibernate-webcasts-series.aspx" /><summary xml:base="http://ayende.com/blog/" type="html">&lt;p&gt;&lt;a href="http://blog.wekeroad.com/"&gt;Rob Conery&lt;/a&gt; and I had sat down and started recording a &lt;a href="http://tekpub.com/preview/nhibernate"&gt;series of webcasts on NHibernate&lt;/a&gt;, which will show up on &lt;a href="http://tekpub.com/"&gt;TekPub&lt;/a&gt;. TekPub is a paid service, and there are two NHibernate screen casts there already. We plan to have &lt;em&gt;lots&lt;/em&gt; more.&lt;/p&gt;  &lt;p&gt;I got a lot of requests for making my NHibernate courses available to a wider audience. And this is a way for you to get a &lt;em&gt;ton&lt;/em&gt; of NHibernate content. So far the reactions that we got were &lt;em&gt;very&lt;/em&gt; positive.&lt;/p&gt;  &lt;p&gt;Oh, and as a side effect, you get to see NH Prof used by the person who wrote it, you might learn a thing or two about extracting information from the profiler.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/11187.aspx" width="1" height="1"&gt;&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/AYENDE/7BE279B16B2436C7C857D5FBC1B19DC12DA6D5BD"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/AYENDE/7BE279B16B2436C7C857D5FBC1B19DC12DA6D5BD"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/ysJIEicpaKw" height="1" width="1"&gt;</summary><author><name>Ayende Rahien</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/AyendeRahien"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/AyendeRahien</id><title type="html">Ayende @ Rahien</title><link rel="alternate" href="http://ayende.com/blog/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1256384444789"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-2122996666044832186">tag:google.com,2005:reader/item/55f2f28d05aaea42</id><category term="Validator" scheme="http://www.blogger.com/atom/ns#" /><category term="Fluent-configuration" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">NHibernate.Validator : The “Satisfy” way of custom Validators</title><published>2009-10-24T10:00:00Z</published><updated>2009-10-24T10:00:01Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-satisfy-way-of.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/2122996666044832186/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/10/nhibernatevalidator-satisfy-way-of.html#comment-form" title="1 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">The Satisfy (perhaps it sound familiar to some SharpTestsEx users ;) ).  To show how it work the example is a constraint for Person.Name: a Name is significant when it has more than three characters, is composed by letters and the first letter is in uppercase.  To create a that validator, in the classic way, we should create an Attribute implementing IRuleArgs and then a class implementing &lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F10%2Fnhibernatevalidator-satisfy-way-of.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=SfWK6bXvzLI:pdKBD3bMMgo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1255040840029"><id gr:original-id="/blogs/billy_mccafferty/archive/2009/10/08/a-s-arp-project-case-study.aspx">tag:google.com,2005:reader/item/bd817c0e5492ca5a</id><category term="S#arp Architecture" scheme="http://devlicio.us/blogs/billy_mccafferty/archive/tags/S_2300_arp+Architecture/default.aspx" /><title type="html">A S#arp Project Case Study</title><published>2009-10-08T18:55:00Z</published><updated>2009-10-08T18:55:00Z</updated><link rel="alternate" href="http://devlicio.us/blogs/billy_mccafferty/archive/2009/10/08/a-s-arp-project-case-study.aspx" type="text/html" /><content xml:base="http://devlicio.us/blogs/billy_mccafferty/default.aspx" xml:lang="en" type="html">&lt;p&gt;Like &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/10/08/an-automapper-success-story.aspx"&gt;Jimmy Bogard&lt;/a&gt;, I was pleased to read &lt;a href="http://groups.google.com/group/sharp-architecture/browse_thread/thread/9df324a3dc36decb"&gt;a post from Howard van Rooijen&lt;/a&gt; on the S#arp Architecture forums concerning the use of &lt;a href="http://www.sharparchitecture.net/"&gt;S#arp Architecture&lt;/a&gt; and Bogard&amp;#39;s &lt;a href="http://www.codeplex.com/AutoMapper"&gt;AutoMapper&lt;/a&gt; in the timely development of &lt;a href="http://www.fancydressoutfitters.co.uk" rel="nofollow"&gt;http://www&lt;/a&gt;&lt;a href="http://www.fancydressoutfitters.co.uk"&gt;.fancydressoutfitters.co.uk&lt;/a&gt;.  With a big thanks to Howard, he has also taken the time to provide a number of great blog posts which walk the reader through his experiences, challenges, solutions, and lessons learned with respect to developing a commercial, greenfield application using ASP.NET MVC.&lt;/p&gt;
&lt;p style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Hello &lt;/span&gt;&lt;span style="font-size:13px;border-collapse:collapse;white-space:pre"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;S#arp Architecture Community&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;,&lt;/span&gt;&lt;a href="http://www.sharparchitecture.net/"&gt;&lt;img border="0" src="http://devlicio.us/resized-image.ashx/__size/550x0/__key/CommunityServer.Components.UserFiles/00.00.00.21.06/logo_5F00_web_5F00_gif.gif" style="border:0;float:right" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;I just wanted to let you know that a S#arp Architecture based e-commerce site has just been released into the wild: &lt;/span&gt;&lt;a href="http://www.fancydressoutfitters.co.uk/"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;http://www.&lt;/span&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;fancydressoutfitters.co.uk&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;For those who are interested - here&amp;#39;s a little background:&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;- We ran the project using Scrum (managing the project with &lt;/span&gt;&lt;a href="http://scrumforteamsystem.com/"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Scrum for Team System&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style="padding-left:30px"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;- Delivered in 20 weeks: 10 x 2 week iterations&lt;br&gt;- We extended the core S#arp Architecture framework (support for multiple databases, ViewModels etc...)&lt;br&gt;
- Integrated other OSS projects into the solution:&lt;br&gt;  - N2CMS&lt;br&gt;  - Spark View Engine&lt;br&gt;  - xVal Validation Framework&lt;br&gt;  - AutoMapper (for entity / view model mapping)&lt;br&gt;  - PostSharp (for cross cutting concerns - logging, performance counters, caching)&lt;br&gt;

  - MBUnit / Gallio for our BDD Framework&lt;br&gt;  - Solr &amp;amp; SolrNet for Search and Faceted Navigation&lt;br&gt;- Over 700 BDD Specs&lt;br&gt;- Solution
performs very well - 1000 concurrent users per web server, generating
around 180 pages per second across 2x single quad core 64bit servers.&lt;br&gt;

&lt;/span&gt;
&lt;div&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;If
you&amp;#39;re really interested two of the developers in the team (James
Broome &amp;amp; Jon George who have both posted to this forum) &amp;amp;
myself have blogged our thoughts &amp;amp; experiences developing this
solution and working with S#arp Architecture:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-size:15px"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;;font-style:normal;font-variant:normal;font-weight:normal;font-size:7pt;line-height:normal;font-size-adjust:none;font-stretch:normal"&gt;&lt;span style="font-size:small"&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/08/24/asp-net-mvc-separation-of-concerns-amongst-team-members.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;ASP.NET
MVC - Separation of concerns amongst team members&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/09/16/asp-net-mvc-controllers-bdd-the-perfect-match-part-1-the-homecontroller.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;ASP.NET
MVC - Controllers + BDD = The perfect match? (Part 1: The HomeController)&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/09/23/asp-net-mvc-controllers-bdd-the-perfect-match-part-2-log-on-and-log-off-with-the-accountcontroller.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;ASP.NET
MVC - Controllers + BDD = The perfect match? (Part 2: Log On and Log Off with
the AccountController)&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/10/06/the-importance-of-conventions-from-asp-net-mvc-to-a-successful-project-team.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;The
importance of conventions – from ASP.NET MVC to a successful project team&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/howardvanrooijen/archive/2009/09/13/the-value-and-benefits-of-asp-net-mvc.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;The
Value and Benefits of ASP.NET MVC&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/10/03/optimising-an-asp-net-mvc-web-site-part-1-introduction.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Optimising
an ASP.NET MVC web site part 1 - Introduction&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/10/03/optimising-an-asp-net-mvc-web-site-part-2-database-and-nhibernate.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Optimising
an ASP.NET MVC web site part 2 - Database and NHibernate&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/09/how-to-improve-your-yslow-score-under-iis7.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;How
to improve your YSlow score under IIS7&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/howardvanrooijen/archive/2009/08/25/cloaking-your-asp-net-mvc-web-application-on-iis-7.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Cloaking
your ASP.NET MVC Web Application on IIS 7&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2008/07/22/why-bdd-works-for-agile.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Why
BDD works for Agile&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2008/12/15/behaviour-driven-development-not-just-for-acceptance-testing.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Behaviour
Driven Development - not just for Acceptance Testing&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/jamesbroome/archive/2009/04/24/why-i-like-n2-cms.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Why
I like N2 CMS&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://consultingblogs.emc.com/howardvanrooijen/archive/2009/09/11/microsoft-open-source-and-codeplex-foundation.aspx"&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;Microsoft,
Open Source and Codeplex Foundation&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;I wanted to say a HUGE
thank-you to everyone in this community for all the passion, energy,
knowledge and help you provide on a daily basis. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;S#arp Architecture is a wonderful framework that truly is greater than the sum of its parts.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:arial,helvetica,sans-serif"&gt;/Howard&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Thanks for sharing Howard and good luck with the venture!  (There are other S#arp projects in the wild &lt;a href="http://groups.google.com/group/sharp-architecture/browse_thread/thread/9df324a3dc36decb"&gt;discussed in the S#arp forums&lt;/a&gt;...go take a look!)&lt;/p&gt;
&lt;p&gt;Billy McCafferty&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=52474" width="1" height="1"&gt;</content><author><name>Billy</name></author><source gr:stream-id="feed/http://devlicio.us/blogs/billy_mccafferty/atom.aspx"><id>tag:google.com,2005:reader/feed/http://devlicio.us/blogs/billy_mccafferty/atom.aspx</id><title type="html">Billy McCafferty</title><link rel="alternate" href="http://devlicio.us/blogs/billy_mccafferty/default.aspx" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1255027827377"><id gr:original-id="http://ayende.com/Blog/archive/2009/10/08/choosing-between-active-record-fluent-nhibenrate-and-nhibernate.aspx">tag:google.com,2005:reader/item/57a6dff9cbe6bdf8</id><category term="NHibernate" /><title type="html">Choosing between Active Record, Fluent NHibernate and NHibernate</title><published>2009-10-08T16:42:00Z</published><updated>2009-10-08T16:42:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/AyendeRahien/~3/8YajYEnEXEE/choosing-between-active-record-fluent-nhibenrate-and-nhibernate.aspx" type="text/html" /><link rel="canonical" href="http://ayende.com/Blog/archive/2009/10/08/choosing-between-active-record-fluent-nhibenrate-and-nhibernate.aspx" /><summary xml:base="http://ayende.com/blog/" type="html">&lt;p&gt;A &lt;a href="http://nhprof.uservoice.com/pages/24233-new-posts-suggestions/suggestions/267650-choosing-between-active-record-fluent-nhibenrate-and-nhibernate?ref=title"&gt;forum question&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have seen videos where you created a domain model using ActiveRecord in real-time... elaborate on when and how you move to using full Hibernate in more detail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The problem with presentations such as the one described in the question is that they are cheating. Oh, I really do work things on the fly, but it is like asking me to type with my eyes closed (as I am doing right now, just to see if I can).&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;can&lt;/em&gt; do that, but it doesn’t really say much about my typing skills. The type of models that I create live tend to be very simple ones, things that I have done for dozens and hundreds of times. Building a model live on stage &lt;em&gt;looks&lt;/em&gt; impressive, especially since I insist of the people in the audience picking the model. But it really isn’t that hard.&lt;/p&gt;
&lt;p&gt;That said, the actual question is more interesting, what should you choose? Active Record, Fluent NHibernate or mapping files?&lt;/p&gt;
&lt;p&gt;I, personally, like using mapping files, they are simple, uncomplicated and expose everything that NHibernate can do. Active Record is nice if you want to put the persistence definition right there along the class definition. Another major advantage of Active Record is that it is working &lt;em&gt;hard&lt;/em&gt; to infer things for you. It makes working with it very easy.&lt;/p&gt;
&lt;p&gt;Fluent NHibernate is mapping using C#. I don’t quite see the point there, especially since in some things FN decided to diverge from the NHibernate terminology, but I get why people love it. The part about it that I simply adore is the auto mapping support. That is a great way of getting things started.&lt;/p&gt;
&lt;p&gt;But usually, even if I am using Fluent NHibernate or Active Record, I am mostly using them as scaffolding. At some point, I’ll ask them to generate the HBM for me and start working with them.&lt;/p&gt;
&lt;p&gt;That is me, however, your mileage might vary.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/11137.aspx" width="1" height="1"&gt;&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/AYENDE/D0BEA50ACE6A7F004A145F6BC85E5285C42B04D4"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/AYENDE/D0BEA50ACE6A7F004A145F6BC85E5285C42B04D4"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/8YajYEnEXEE" height="1" width="1"&gt;</summary><author><name>Ayende Rahien</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/AyendeRahien"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/AyendeRahien</id><title type="html">Ayende @ Rahien</title><link rel="alternate" href="http://ayende.com/blog/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1254591774986"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-5021366884786552915">tag:google.com,2005:reader/item/18032589ec588dcb</id><category term="NHibernate" scheme="http://www.blogger.com/atom/ns#" /><category term="ORM" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">How you shouldn’t write your mapping</title><published>2009-10-03T16:46:00Z</published><updated>2009-10-03T16:48:43Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/10/how-you-shouldnt-write-your-mapping.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/5021366884786552915/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/10/how-you-shouldnt-write-your-mapping.html#comment-form" title="0 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">More than one time, in my courses, in this blog and in various NH’s users list, I talked about a rule of thumb about mappings: not try to be clear because it obscures.  Have a look to this mapping:  &lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F10%2Fhow-you-shouldnt-write-your-mapping.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=zjx99rKubXc:MEfetZ6PfDs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1254172598628"><id gr:original-id="tag:blogger.com,1999:blog-3924739636407907202.post-1711923950655965442">tag:google.com,2005:reader/item/c005c6f0dc7d1fda</id><category term="NHibernate" scheme="http://www.blogger.com/atom/ns#" /><category term="Azure" scheme="http://www.blogger.com/atom/ns#" /><category term="English" scheme="http://www.blogger.com/atom/ns#" /><title type="html">Quick news: NHibernate with SQL-Azure</title><published>2009-09-28T15:38:00Z</published><updated>2009-09-28T15:38:58Z</updated><link rel="alternate" href="http://fabiomaulo.blogspot.com/2009/09/quick-news-nhibernate-with-sql-azure.html" type="text/html" /><link rel="replies" href="http://fabiomaulo.blogspot.com/feeds/1711923950655965442/comments/default" title="Post Comments" type="application/atom+xml" /><link rel="replies" href="http://fabiomaulo.blogspot.com/2009/09/quick-news-nhibernate-with-sql-azure.html#comment-form" title="0 Comments" type="text/html" /><content xml:base="http://fabiomaulo.blogspot.com/" type="html">Just ran DAOs integration tests (the same of this post) in SQL-AZURE.  All work… even the SchemaExport.  well…well… Not all glitters is gold ;)  Exception: “Heaps can not be replicated tables. Please create a clustered index for the table.”&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/95o4kton06vdt4stuc6a135e9s/468/60#http%3A%2F%2Ffabiomaulo.blogspot.com%2F2009%2F09%2Fquick-news-nhibernate-with-sql-azure.html" width="100%" height="60" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Hunabku?a=H1FkIRiYNw8:1-LicT4tw6s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Hunabku?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;</content><author><name>Fabio Maulo</name></author><source gr:stream-id="feed/http://fabiomaulo.blogspot.com/feeds/posts/default"><id>tag:google.com,2005:reader/feed/http://fabiomaulo.blogspot.com/feeds/posts/default</id><title type="html">HunabKu</title><link rel="alternate" href="http://fabiomaulo.blogspot.com/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1251664229533"><id gr:original-id="http://ayende.com/Blog/archive/2009/08/30/avoid-soft-deletes.aspx">tag:google.com,2005:reader/item/644cebdd34e25d1f</id><category term="NHibernate" /><title type="html">Avoid Soft Deletes</title><published>2009-08-30T19:27:00Z</published><updated>2009-08-30T19:27:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/AyendeRahien/~3/eEZwQbeEf2k/avoid-soft-deletes.aspx" type="text/html" /><link rel="canonical" href="http://ayende.com/Blog/archive/2009/08/30/avoid-soft-deletes.aspx" /><summary xml:base="http://ayende.com/blog/" type="html">&lt;p&gt;One of the annoyances that we have to deal when building enterprise applications is the requirement that no data shall be lost. The usual response to that is to introduce a WasDeleted or an IsActive column in the database and implement deletes as an update that would set that flag.&lt;/p&gt;  &lt;p&gt;Simple, easy to understand, quick to implement and explain.&lt;/p&gt;  &lt;p&gt;It is also, quite often, wrong.&lt;/p&gt;  &lt;p&gt;The problem is that deletion of a row or an entity is rarely a simple event. It effect not only the data in the model, but also the &lt;em&gt;shape&lt;/em&gt; of the model. That is why we have foreign keys, to ensure that we don’t end up with Order Lines that don’t have a parent Order. And that is just the simplest of issues. Let us consider the following model:&lt;/p&gt;  &lt;blockquote&gt;   &lt;div&gt;     &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; Order
{
    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;virtual&lt;/span&gt; ICollection&amp;lt;OrderLines&amp;gt; OrderLines { get;set; }
}

&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; OrderLine
{
    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;virtual&lt;/span&gt; Order Order { get;set; }
}

&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; Customer
{
    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;virtual&lt;/span&gt; Order LastOrder { get;set; }
}&lt;/pre&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let us say that we want to delete an order. What should we do? That is a business decision, actually. But it is one that is enforced by the DB itself, keeping the data integrity.&lt;/p&gt;

&lt;p&gt;When we are dealing with soft deletes, it is easy to get into situations where we have, for all intents and purposes, corrupt data, because Customer’s LastOrder (which is just a tiny optimization that no one thought about) now points to a soft deleted order.&lt;/p&gt;

&lt;p&gt;Now, to be fair, if you are using NHibernate there are &lt;a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/08/soft-deletes.aspx"&gt;very easy ways to handle that&lt;/a&gt;, which actually handle cascades properly. It is still a more complex solution.&lt;/p&gt;

&lt;p&gt;For myself, I much rather drop the requirement for soft deletes in the first place and head directly to &lt;em&gt;why&lt;/em&gt; we care for that. Usually, this is an issue of auditing. You can’t remove data from the database once it is there, or the regulator will have your head on a silver platter and the price of the platter &lt;em&gt;will&lt;/em&gt; be deducted from your salary.&lt;/p&gt;

&lt;p&gt;The fun part is that it is so much easier to implement that with NHibernate, for that matter, I am &lt;em&gt;not&lt;/em&gt; going to show you how to implement that feature, I am going to show how to implement a related one and leave building the auditable deletes as an exercise for the reader :-)&lt;/p&gt;

&lt;p&gt;Here is how we implement audit trail for updates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;div&gt;
    &lt;pre style="border-bottom-style:none;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; SeparateTableLogEventListener : IPreUpdateEventListener
{
    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;bool&lt;/span&gt; OnPreUpdate(PreUpdateEvent updateEvent)
    {
        var sb = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; StringBuilder(&lt;span style="color:#006080"&gt;"Updating "&lt;/span&gt;)
            .Append(updateEvent.Entity.GetType().FullName)
            .Append(&lt;span style="color:#006080"&gt;"#"&lt;/span&gt;)
            .Append(updateEvent.Id)
            .AppendLine();

        &lt;span style="color:#0000ff"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; updateEvent.OldState.Length; i++)
        {
            &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (Equals(updateEvent.OldState[i], updateEvent.State[i])) &lt;span style="color:#0000ff"&gt;continue&lt;/span&gt;;

            sb.Append(updateEvent.Persister.PropertyNames[i])
                .Append(&lt;span style="color:#006080"&gt;": "&lt;/span&gt;)
                .Append(updateEvent.OldState[i])
                .Append(&lt;span style="color:#006080"&gt;&amp;quot; =&amp;gt; &amp;quot;&lt;/span&gt;)
                .Append(updateEvent.State[i])
                .AppendLine();
        }

        var session = updateEvent.Session.GetSession(EntityMode.Poco);
        session.Save(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; LogEntry
        {
            WhatChanged = sb.ToString()
        });
        session.Flush();

        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff"&gt;false&lt;/span&gt;;
    }
}&lt;/pre&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is an example, so it is pretty raw, but it should be create what is going on.&lt;/p&gt;

&lt;p&gt;Your task, if you agree to accept it, is to build a similar audit listener for deletes. This message will self destruct whenever it feels like.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/11054.aspx" width="1" height="1"&gt;&lt;p&gt;&lt;a href="http://theloungenet.com/feeds/redirect/DOTNETRSS/AYENDE/F99257B41745044886DCCDBC0B9776C0A4C0B04D"&gt;&lt;img src="http://theloungenet.com/feeds/img/DOTNETRSS/AYENDE/F99257B41745044886DCCDBC0B9776C0A4C0B04D"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/eEZwQbeEf2k" height="1" width="1"&gt;</summary><author><name>Ayende Rahien</name></author><source gr:stream-id="feed/http://feeds.feedburner.com/AyendeRahien"><id>tag:google.com,2005:reader/feed/http://feeds.feedburner.com/AyendeRahien</id><title type="html">Ayende @ Rahien</title><link rel="alternate" href="http://ayende.com/blog/" type="text/html" /></source></entry><entry gr:crawl-timestamp-msec="1251539671397"><id gr:original-id="45f813f2-f1c4-4eda-a619-288e3cadc793:497">tag:google.com,2005:reader/item/974956bcb5cf97f7</id><category term="Fluent NHibernate" scheme="http://nhforge.org/blogs/nhibernate/archive/tags/Fluent+NHibernate/default.aspx" /><title type="html">Fluent NHibernate 1.0</title><published>2009-08-29T00:33:00Z</published><updated>2009-08-29T00:33:00Z</updated><link rel="alternate" href="http://feedproxy.google.com/~r/NHibernateBlog/~3/UiAR81uTBCo/fluent-nhibernate-1-0.aspx" type="text/html" /><link rel="canonical" href="http://nhforge.org/blogs/nhibernate/archive/2009/08/29/fluent-nhibernate-1-0.aspx" /><summary xml:base="http://nhforge.org/blogs/nhibernate/default.aspx" type="html">&lt;p&gt;The 1.0 RTM is now available &lt;a href="http://fluentnhibernate.org/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those of you that don&amp;#39;t know, &lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt; is for helping you map entities with &lt;a href="http://nhforge.org"&gt;NHibernate&lt;/a&gt;. It&amp;#39;s based firmly on the practice of &lt;a href="http://en.wikipedia.org/wiki/Convention_over_configuration"&gt;convention-over-configuration&lt;/a&gt;, and can be used in a mapping-per-class style using our &lt;a href="http://wiki.fluentnhibernate.org/Fluent_mapping"&gt;fluent interface&lt;/a&gt;, or let our &lt;a href="http://wiki.fluentnhibernate.org/Auto_mapping"&gt;automapper&lt;/a&gt; map your entities itself.&lt;/p&gt;

&lt;p&gt;This release introduces a few significant changes, and a lot of insignificant ones. You should refer to the &lt;a href="http://wiki.fluentnhibernate.org/Release_notes_1.0"&gt;1.0 release notes&lt;/a&gt; for an overview of what&amp;#39;s changed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://wiki.fluentnhibernate.org"&gt;wiki&lt;/a&gt; has also been upgraded to use different software which should hopefully stop people being blocked, and make it a bit more stable; the upgrade included completely rewriting all of the pages, so don&amp;#39;t anyone say that it&amp;#39;s out of date.&lt;/p&gt;

&lt;p&gt;You can get the binaries from the our &lt;a href="http://fluentnhibernate.org/downloads"&gt;downloads page&lt;/a&gt;, or get the source from the &lt;a href="http://github.com/jagregory/fluent-nhibernate"&gt;github site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Special thanks go out to the Fluent NHibernate team, Paul Batum, Hudson Akridge, Andrew Stewart, and Stuart Childs. Each of them has put in time and effort above what was asked of them, and they&amp;#39;ve all felt guilty when not contributing, which is great. Thanks also to all the testers and contributors we&amp;#39;ve had over the months. Specifically Darko Conrad, for finding about 30 separate issues with the release candidiate; Everett Muniz and his subclasses, who now has a test of his own; and Kevin Dente, for deciding to moan about our method names only &lt;em&gt;after&lt;/em&gt; months of work and a release candidate. I owe everyone beers if ever I&amp;#39;m in your area.&lt;/p&gt;

&lt;p&gt;Fabio Maulo, Ayende, and the rest of the NHibernate team: Thanks for a great tool. NHibernate is a shining example of all that is good in open source in the .Net world.&lt;/p&gt;

&lt;p&gt;...and with that, I&amp;#39;m going on &lt;a href="http://maps.google.co.uk/maps?f=d&amp;amp;source=s_d&amp;amp;saddr=Sydney&amp;amp;daddr=Brisbane+to:Cairns&amp;amp;hl=en&amp;amp;geocode=&amp;amp;mra=ls&amp;amp;sll=-25.656382,152.880249&amp;amp;sspn=1.383954,1.851196&amp;amp;ie=UTF8&amp;amp;ll=-25.522615,152.358398&amp;amp;spn=22.065278,29.619141&amp;amp;z=5"&gt;holiday&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both"&gt;&lt;/div&gt;&lt;img src="http://nhforge.org/aggbug.aspx?PostID=497" width="1" height="1"&gt;&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/~ah/f/fa8lvl84s9urqe9rt6m7fhi0ag/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fnhforge.org%2Fblogs%2Fnhibernate%2Farchive%2F2009%2F08%2F29%2Ffluent-nhibernate-1-0.aspx" width="100%" height="280" frameborder="0" scrolling="no" marginwidth="0" marginheight="0"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/NHibernateBlog/~4/UiAR81uTBCo" height="1" width="1"&gt;</summary><author><name>James Gregory</name></author><source gr:stream-id="feed/http://feedproxy.google.com/NHibernateBlog"><id>tag:google.com,2005:reader/feed/http://feedproxy.google.com/NHibernateBlog</id><title type="html">NHibernate blog</title><link rel="alternate" href="http://nhforge.org/blogs/nhibernate/default.aspx" type="text/html" /></source></entry></feed>

