R – Fluent NHibernate DiscriminateSubClassesOnColumn Issue

fluent-nhibernatenhibernatenhibernate-mapping

I said Fluent NHibernate in the subject, but I think this is an NHibernate question. However, I didn't want to confuse things by leaving out details.

I'm using Fluent NHibernate 1.0.0.593 with NHibernate 2.1.0.4000.

First a little background…

I have a base class with three implementation classes that I'm trying to map using the DiscriminateSubClassesOnColumn/SubclassMap.DiscriminatorValue Fluent NHibernate syntax. The sub classes represent responses I can get from three different third parties data providers. The information is the generally same, but the relationships are different (one response type can have multiple addresses, another can only have one, etc.).

I had Fluent NHibernate extract the NHibernate configuration xml it was generating and based on my understanding of what the discriminator and subclass blocks should look like, the configuration appears to be generating correctly (which is why I'm thinking this is an NHibernate question, not a Fluent NHibernate one).

The "problem" that I'm seeing is that for the initial query from the database, NHibernate appears to be scanning the subclasses and doing all the one-to-one relationships as joins in the initial query. Since some of the sub class have the same child type as a one-to-many relationship, this is causing an error when I try to retrieve one of these other types.

I'll post the generated NHibernate configuration as well for reference.

Anyone have any ideas on how to control this or maybe what I'm doing wrong?

Thanks.

Best Answer

    <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="Unknown" name="PersonValidationResponse, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="PersonValidationResponse">
    <id name="ResponseId" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="pk_ResponseId" />
      <generator class="identity" />
    </id>
    <discriminator type="PersonValidationResponseType, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <column name="ResponseType" />
    </discriminator>
    <property name="CreatedBy" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="CreatedBy" />
    </property>
    <property name="CreatedDate" type="System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="CreatedDate" />
    </property>
    <many-to-one class="PersonValidationRequest, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Request">
      <column name="fk_RequestId" />
    </many-to-one>
    <subclass name="ResponseTypeAResponse, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="ResponseTypeA">
      <one-to-one cascade="all" class="PersonValidationAddress, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" foreign-key="fk_ResponseId" lazy="false" name="Address" property-ref="Response" />
      <one-to-one cascade="all" class="PersonValidationBiographic, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" foreign-key="fk_ResponseId" lazy="false" name="Biographic" property-ref="Response" />
      <one-to-one cascade="all" class="PersonValidationPhone, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" foreign-key="fk_ResponseId" lazy="false" name="Phone" property-ref="Response" />
      <property name="ResponseStatus" type="ResponseStatus, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="ResponseStatus" />
      </property>
      <property name="RawResponse" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="RawResponse" />
      </property>
      <bag cascade="all-delete-orphan" lazy="false" name="Alerts" table="PersonValidationResponseAlert">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <many-to-many class="PersonValidationAlert, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <column name="fk_AlertId" />
        </many-to-many>
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Scores" table="PersonValidationResponseScore">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationScore, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Exceptions" table="PersonValidationResponseException">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationException, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
    </subclass>
    <subclass name="ResponseTypeBResponse, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="ResponseTypeB">
      <one-to-one cascade="all" class="PersonValidationWatchList, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" foreign-key="fk_ResponseId" lazy="false" name="WatchListHit" property-ref="Response" />
      <property name="ResponseStatus" type="ResponseStatus, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="ResponseStatus" />
      </property>
      <property name="RawResponse" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="RawResponse" />
      </property>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Addresses" table="PersonValidationAddress">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationAddress, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Biographics" table="PersonValidationBiographic">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationBiographic, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Phones" table="PersonValidationPhone">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationPhone, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" lazy="false" name="Alerts" table="PersonValidationResponseAlert">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <many-to-many class="PersonValidationAlert, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <column name="fk_AlertId" />
        </many-to-many>
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Scores" table="PersonValidationResponseScore">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationScore, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Exceptions" table="PersonValidationResponseException">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationException, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
    </subclass>
    <subclass name="ResponseTypeCResponse, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="ResponseTypeC">
      <property name="ResponseStatus" type="ResponseStatus, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="ResponseStatus" />
      </property>
      <property name="RawResponse" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <column name="RawResponse" />
      </property>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Addresses" table="PersonValidationAddress">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationAddress, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Biographics" table="PersonValidationBiographic">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationBiographic, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="CreditAccounts" table="PersonValidationCreditAccount">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationCreditAccount, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Phones" table="PersonValidationPhone">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationPhone, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="WatchListHits" table="PersonValidationWatchList">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationWatchList, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" lazy="false" name="Alerts" table="PersonValidationResponseAlert">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <many-to-many class="PersonValidationAlert, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
          <column name="fk_AlertId" />
        </many-to-many>
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Scores" table="PersonValidationResponseScore">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationScore, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
      <bag cascade="all-delete-orphan" inverse="true" lazy="false" name="Exceptions" table="PersonValidationResponseException">
        <key>
          <column name="fk_ResponseId" />
        </key>
        <one-to-many class="PersonValidationException, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </bag>
    </subclass>
    <subclass name="UnknownResponse, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" discriminator-value="Unknown" />
  </class>
</hibernate-mapping>
Related Topic