views:

19

answers:

0

I'm trying to do almost exactly the same thing as this post: http://colinjack.blogspot.com/2008/03/nhibernate-working-around-lack-of.html

but I can't get the suggested solution to work for me.

Essentially I have one main class, which has a reference to an abstract class. The abstract class has several implementations. I want the common fields on the abstract class to live in the same table as the definition of the main class. The implementations of the abstract class with different fields will have their own tables (table per subclass).

My tables look like this:

TABLE MainClass: ID INT (IDENTITY(1,1)), MainField INT, AbstractComponentField1 INT, ComponentType VARCHAR
TABLE ComponentSubTypeA: MainClassID INT, ComponentSubTypeAField1 INT
TABLE ComponentSubTypeB: MainClassID INT, ComponentSubTypeBField1 VARCHAR

My classes:


class MainClass
int ID {get;set;}
int mainField {get;set;}
AbstractComponent myComponent {get;set;}

abstract class AbstractComponent
int ID {get;set;}
int abstract ComponentField1 {get;set;}
MainClass MainClass {get;set;}

class ComponentSubTypeA: AbstractComponent
int componentSubTypeAField1 {get;set;}

class ComponentSubTypeB: AbstractComponent
string componentSubTypeBField1 {get;set;}

My mapping:

<class name="MainClass" table="MainClass" lazy="false">
    <id name="ID" column="ID">
        <generator class="native"/>
    </id>

    <one-to-one name="myComponent" cascade="all">
    <property name="mainField" column="MainField">
</class>

<class name="AbstractComponent" abstract=true table="MainClass">
    <id name="ID" column="ID">
        <generator class="foreign">
              <param name="property">MainClass</param>
        </generator>
    </id>
    <discriminator column="ComponentType" type="string">
    <one-to-one constrained="true" name="MainClass">
    <property name="abstractComponentField1" column="AbstractComponentField1">

    <subclass name="ComponentSubTypeA" discriminator-value="A">
         <join table="ComponentSubTypeA">
                <key column="MainClassID">
                <property name="componentSubTypeAField1" column="ComponentSubTypeAField1">
         </join>
    </subclass>

    <subclass name="ComponentSubTypeB" discriminator-value="B">
         <join table="ComponentSubTypeB">
                <key column="MainClassID">
                <property name="componentSubTypeBField1" column="ComponentSubTypeBField1">
         </join>
    </subclass>

</class>

When I try to save an instance of MainClass, NHibernate tries to do two inserts in a row, instead of an insert and an update. The first insert creates the MainClass and inserts the main field. The second insert tries to insert into the same table (with the correct main class ID) the discriminator value and the abstract field.

Example: INSERT INTO MainClass(MainField) Values (..).
select SCOPE_IDENTITY (get the ID that was just inserted, let's say it was 5) INSERT INTO MainClass(AbstractComponentField1, ComponentType, ID) Values (..,'A', 5)

It seems that the "solution" offered in the linked post doesn't actually work. How do I tell the entity to SHARE the row, and not attempt to create a new one in the same table?