Mixing inheritance mapping strategies in NHibernate

Posted by MylesRip on Stack Overflow See other posts from Stack Overflow or by MylesRip
Published on 2010-04-26T18:01:50Z Indexed on 2010/04/26 18:03 UTC
Read the original article Hit count: 476

I have a rather large inheritance hierarchy in which some of the subclasses add very little and others add quite a bit. I don't want to map the entire hierarchy using either "table per class hierarchy" or "table per subclass" due to the size and complexity of the hierarchy. Ideally I'd like to mix mapping strategies such that portions of the hierarchy where the subclasses add very little are combined into a common table a la "table per class hierarchy" and subclasses that add a lot are broken out into a separate table. Using this approach, I would expect to have 2 or 3 tables with very little wasted space instead of either 1 table with lots of fields that don't apply to most of the objects, or 20+ tables, several of which would have only a couple of columns.

In the NHibernate Reference Documentation version 2.1.0, I found section 8.1.4 "Mixing table per class hierarchy with table per subclass". This approach switches strategies partway down the hierarchy by using:

...
<subclass ...>
    <join ...>
        <property ...>
        ...
    </join>
</subclass>
...

This is great in theory. In practice, though, I found that the schema was too restrictive in what was allowed inside the "join" element for me to be able to accomplish what I needed.

Here is the related part of the schema definition:

<xs:element name="join">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="subselect" minOccurs="0" />
            <xs:element ref="comment" minOccurs="0" />
            <xs:element ref="key" />
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element ref="property" />
                <xs:element ref="many-to-one" />
                <xs:element ref="component" />
                <xs:element ref="dynamic-component" />
                <xs:element ref="any" />
                <xs:element ref="map" />
                <xs:element ref="set" />
                <xs:element ref="list" />
                <xs:element ref="bag" />
                <xs:element ref="idbag" />
                <xs:element ref="array" />
                <xs:element ref="primitive-array" />
            </xs:choice>
            <xs:element ref="sql-insert" minOccurs="0" />
            <xs:element ref="sql-update" minOccurs="0" />
            <xs:element ref="sql-delete" minOccurs="0" />
        </xs:sequence>
        <xs:attribute name="table" use="required" type="xs:string" />
        <xs:attribute name="schema" type="xs:string" />
        <xs:attribute name="catalog" type="xs:string" />
        <xs:attribute name="subselect" type="xs:string" />
        <xs:attribute name="fetch" default="join">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="join" />
                    <xs:enumeration value="select" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="inverse" default="false" type="xs:boolean">
        </xs:attribute>
        <xs:attribute name="optional" default="false" type="xs:boolean">
        </xs:attribute>
    </xs:complexType>
</xs:element>

As you can see, this allows the use of "property" child elements or "component" child elements, but not both. It also doesn't allow for "subclass" child elements to continue the hierarchy below the point at which the strategy was changed.

Is there a way to accomplish this?

© Stack Overflow or respective owner

Related posts about nhibernate

Related posts about nhibernate-mapping