views:

46

answers:

0

I've been trying to wrap my head around subclasses and joined subclasses in Fluent nHibernate for a few days now without making any sort of headway. I've looked at the wiki but it doesn't seem to give me enough information, and googling returns me old results that uses depreciated code or are seemingly unrelated.

I just want a simple example, if that's at all possible

I have four tables that look like this:

+--------------+  +---------------+  +---------------+
| Animal       |  | AnimalType    |  | Reptile       |
+==============+  +===============+  +===============+
| Id           |  | Id            |  | AnimalId      |
| AnimalTypeId |  | Description   |  | TongueLength  |
| version      |  +---------------+  +---------------+
+--------------+

So the Animal table has a FK that references the AnimalType table, a look up table containing just 1 Id, as a test,

1 = Reptile

The idea is that the AnimalTypeId column is my discriminator column that splits up my subclasses, and each of the animal tables (Reptile) have FK primary keys that are referencing the Id from the Animal table depending on its AnimalTypeId.

So my C# classes look like this

public class Animal
{
    public virtual int Id {get;set;}
    public virtual AnimalType AnimalType {get;set;}
    public virtual int Version {get; protected set;}
}

public class AnimalType
{
    public virtual int Id {get;set;}
    public virtual string Description {get;set;}
}

public class Reptile : Animal
{
    public virtual int AnimalId {get;set;}
    public virtual float TongueLength {get;set;}
}

How do I map this as a subclass-per-table?

Here's my current mapping.

public class AnimalMap : ClassMap<Animal>
{
    public AnimalMap()
    {
        Table("Animal");
        Id(x => x.Id);
        DiscriminateSubClassesOnColumn("AnimalTypeId",0)
            .AlwaysSelectWithValue();
        Version(x => x.Version);
    }
}

public class ReptileMap: SubclassMap<Reptile>
{
    public ReptileMap()
    {
        DiscriminatorValue(1);
        Table("Reptile");
        KeyColumn("AnimalId");
        Map(x => x.TongueLength);
    }
}

public class AnimalTypeMap : ClassMap<AnimalType>
{
    public AnimalTypeMap ()
    {
        Table("AnimalTypeMap");
        Id(x => x.Id);
        Map(x => x.Description);
    }
}

It almost works, it just doesn't seem to be picking up that the subclass comes from a different table. The HBM mapping is below.

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" discriminator-value="0" schema="dbo" name="NamespaceDefault.Animal, SolEntity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Animal">
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <discriminator type="Int32" force="true">
      <column name="AnimalTypeId" />
    </discriminator>
    <version name="Version" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Version" />
    </version>
    <subclass name="NamespaceDefault.Reptile, SolEntity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="1">
      <property name="TongueLength" type="System.Float, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="TongueLength" />
      </property>
    </subclass>
  </class>
</hibernate-mapping>

edit: There was an issue earlier with duplicate entities. Solution is linked in next comment.