I Am Not Myself

Bills.Pay(Developer.Skills).ShouldBeTrue()

Fluent NHibernate Joined Subclass in Separate Assemblies

I have the following solution project structure:

  • Application.Core.Entities
  • Application.Xtend.CustomerName.Entities

In the Core project I have an entity Customer defiend. In the XTend project, I have an entity defined that subclasses Customer named xCustomer (for lack of a better name at this time…).

The idea here is that we have a Core domain model in our application. A customer can then create a new assembly that contains extensions to our core model. When the extension assembly is present a smart IRepository class will return a subclass of the core class instead.

I am attempting to map this relationship in NHibernate. Using Fluent NHibernate I was able to generate this mapping:

 

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   default-lazy="false"
                   assembly="NHibernate.Core.Entites"
                   namespace="NHibernate.Entites"
                   default-access="field.camelcase-underscore">
  <!-- Customer is located in assembly Application.Core.Entities -->
  <class name="Customer" table="Customers"
        xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int64">
      <generator class="native" />
    </id>
    <component name="Name" insert="true" update="true">
      <property name="LastName" column="LastName" length="255"
                type="String" not-null="true">
        <column name="LastName" />
      </property>
      <property name="FirstName" column="FirstName" length="255"
                type="String" not-null="true">
        <column name="FirstName" />
      </property>
    </component>
    <!-- xCustomer is located in assembly Application.XTend.CustomerName.Entities -->
    <joined-subclass name="xCustomer" table="xCustomer">
      <key column="CustomerId" />
      <property name="CustomerType" column="CustomerType"
                length="255" type="String" not-null="true">
        <column name="CustomerType" />
      </property>
    </joined-subclass>
  </class>
</hibernate-mapping>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

But NHib throws the following error:

NHibernate.MappingException: persistent class Application.Entites.xCustomer, Application.Core.Entites not found —> System.TypeLoadException: Could not load type ‘Application.Entites.xCustomer’ from assembly ‘Application.Core.Entites, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’..

Which makes sense xCustomer is not defined in the Core library. I took my quandary to the NHibernate Users mailing list and StackOverflow. After some helpful suggestions and pointers, I discovered that the solution was so obvious that I am somewhat embarrassed that I couldn’t see it.

The hibernate-mapping attributes assembly and namespace are convenient short cuts that allow you to not have to fully qualify your class names. This lets you have the nice mark up , but the name attribute of both class and joined-subclass elements can take a fully qualified assembly name as well.

So the above broken mapping file can be fixed like so:

 

<joined-subclass name="Application.XTend.CustomerName.Entities.xCustomer,
                 Application.XTend.CustomerName.Entities, Version=1.0.0.0,
                 Culture=neutral, PublicKeyToken=null"
                 table="xCustomer">
  <key column="CustomerId" />
  <property name="CustomerType" column="CustomerType" length="255"
            type="String" not-null="true">
    <column name="CustomerType" />
  </property>
</joined-subclass>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This works as I expected it to. So I then took a look at the Fluent-NHibernate source and created a patch complete with working unit tests to resolve the issue and submitted it to the project.

So at the end of the day, I learned something about NHibernate and the Fluent-NHibernate team got a patch to resolve and obscure bug.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: