流利的NHibernate DiscriminateSubClassesOnColumn问题

时间:2009-12-21 20:39:01

标签: nhibernate fluent-nhibernate nhibernate-mapping

我在主题中说过Fluent NHibernate,但我认为这是一个NHibernate问题。但是,我不想通过遗漏细节来混淆事情。

我正在使用Fluent NHibernate 1.0.0.593和NHibernate 2.1.0.4000。

首先是一点背景......

我有一个基类,有三个实现类,我试图使用DiscriminateSubClassesOnColumn / SubclassMap.DiscriminatorValue Fluent NHibernate语法进行映射。子类表示我可以从三个不同的第三方数据提供者获得的响应。信息大致相同,但关系不同(一个响应类型可以有多个地址,另一个只能有一个,等等)。

我让Fluent NHibernate提取它生成的NHibernate配置xml,并根据我对鉴别器和子类块应该是什么样的理解,配置似乎正在生成(这就是为什么我认为这是一个NHibernate问题,不是流利的NHibernate)。

我看到的“问题”是,对于来自数据库的初始查询,NHibernate似乎正在扫描子类并将所有一对一关系作为初始查询中的连接进行。由于某些子类具有与一对多关系相同的子类型,因此当我尝试检索这些其他类型之一时,这会导致错误。

我将发布生成的NHibernate配置以供参考。

任何人对如何控制这个或者我做错了有什么想法?

感谢。

2 个答案:

答案 0 :(得分:0)

    <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>

答案 1 :(得分:0)

不确定这是最好的答案,所以我仍然有兴趣听取其他想法,但我发现一个修复。

将Fetch.Select添加到子类上的任何HasOne关系,似乎强制对这些子类型的查询始终位于单独的SELECT中。在连接会更好的情况下,它最终效率会降低,但它会使异常消失。