0

In my database I have a table for 'User' who has a foreign key constraint to a 'Servant', who has again a foreign key constraint to a 'Person'.

The relationship between 'Servant' and 'Person' is now changed to an inheritance, so that 'Person' is the base class of 'Servant'. In this case NHibernate does not care about the 'Servant' ID anymore and only uses the 'Person' ID.

The only problem I have encountered is the foreign key for the servant in the table 'User' now. Because 'Servant' and 'User' ID did not have to be equal in the past, this is now a huge problem, as NHibernate tries to fetch the 'Servant' of the User by using the 'Servant' ID and looking for it in the 'Person' table.

Is there any solution to this problem to let NHibernate still know about the 'Servant' ID? The absolute last thing I want to do is to change anything in the database.

2 Answers2

0

Yes , you can give a mapping of Servant Collection from User Class. Looks like a Self Referencing foreign key that is mapped to Servant Class, The key is in how you define the mapping where still you can map a ServentID to PersonID.

0

You can use the property-ref attribute to join to a column other than the primary key.


If you tell one lie...

So, you previously had something like this:

<class name="Person">
  <id name="Id"
      column="Id"
      type="Int32"
      generator="native" />
</class>

<class name="Servant">
  <id name="Id"
      column="Id"
      type="Int32"
      generator="native" />
  <many-to-one name="Person"
               column="Person_Id"
               not-null="true"
               unique="true" />
</class>

<class name="User">
  <id name="Id"
      column="Id"
      type="Int32"
      generator="native" />
  <many-to-one name="Servant"
               column="Servant_Id" />
</class>

Without changing the database schema, you've removed the <class name="Servant"> and replaced it with this:

<class name="Person">
  <!-- Rest of Person stays the same, except we insert this: -->
  <joined-subclass name="Servant">
    <key column="Person_Id" />
  </joined-subclass>
</class>

Even though Person_Id is not really the primary key for the Servant table, we've told NHibernate to pretend that it is - which will still work fine, as long as that column is not null and unique. The problem you're running into now is that NHibernate wants to join on User.Servant_Id = Servant.Person_Id, because it thinks that Person_Id is the primary key of the Servant table.

So, how do we fix it? How do we get NHibernate to still join on User.Servant_Id = Servant.Id?

Easy. We simply lie to NHibernate again, and tell it that the User.Servant property shouldn't join to Servant's primary key, but to a different unique column on that table, Id (which actually is the primary key, but shhh, don't tell NHibernate).

First, we need to add Servant's id as a property. We'll name it ServantId so as to not shadow the Id property we inherit from Person. We'll also set insert, update, and generated appropriately to ensure NHibernate allows the database to generate this value.

<joined-subclass name="Servant">
  <key column="Person_Id" />
  <property name="ServantId"
            column="Id"
            insert="false"
            update="false"
            generated="insert" />
</class>

Next, we modify the mapping for User's Servant property, telling it to join to that new property in the other table instead of the primary key.

<many-to-one name="Servant"
             column="Servant_Id"
             property-ref="ServantId" />

Viola! The above description should be enough information to paint all sides of the picture (DB Tables, NH Mappings, C# Classes), but if it's not, let me know and I can be more explicit.

Community
  • 1
  • 1
Daniel Schilling
  • 4,829
  • 28
  • 60