NHiberate加入子类无效的属性

时间:2016-05-04 19:37:43

标签: nhibernate joined-subclass

我正在尝试解决这个问题,其中子类包含一组属性,但引用的表中不存在两个属性。

这两个属性存在于一个扩展表中,该表将FK返回到基表。我不确定如何修改此xml以支持第一个连接的子类并为Extension表添加另一个连接。

我试图简单地为Extension表添加另一个join-subclass,但由于类名相同,映射无效。

    <joined-subclass name="SESProgramAssociationAggregate.SESProgramAssociation" table="SESProgramAssociation" lazy="false">
  <key>
    <column name="BeginDate" />
    <column name="EOId" />
    <column name="PEOrganizationId" />
    <column name="ProgramName" />
    <column name="ProgramTypeId" />
    <column name="UDI" />
  </key>

  <!-- PK properties -->
  <property name="UDI" column="UDI" type="int" not-null="true" insert="false" />
  <property name="ProgramTypeId" column="ProgramTypeId" type="int" not-null="true" insert="false" />
  <property name="PEOrganizationId" column="PEOrganizationId" type="int" not-null="true" insert="false" />
  <property name="BeginDate" column="BeginDate" type="date" not-null="true" insert="false" />
  <property name="ProgramName" column="ProgramName" type="string" length="60" not-null="true" insert="false" />
  <property name="EOId" column="EOId" type="int" not-null="true" insert="false" />

  <!-- Properties -->
  <property name="Eligibility" column="Eligibility" type="bool" />
  <property name="SESDescriptorId" column="SESDescriptorId" type="int" not-null="true" />
  <property name="SEHoursPerWeek" column="SEHoursPerWeek" type="decimal" />
  <property name="HoursPerWeek" column="HoursPerWeek" type="decimal" />
  <property name="MultiplyD" column="MultiplyD" type="bool" />
  <property name="MFragile" column="MFragile" type="bool" />
  <property name="LastEvalDate" column="LastEvalDate" type="date" />
  <property name="ReviewDate" column="ReviewDate" type="date" />
  <property name="BeginDate" column="BeginDate" type="date" />
  <property name="EndDate" column="EndDate" type="date" />
  <property name="EventCode" column="EventCode" type="int" />
  <property name="WrittenConsentDate" column="WrittenConsentDate" type="date" />

</joined-subclass>

生成的最终查询失败,因为它尝试从SESProgramAssociation表引用它们不存在的EventCode和WrittenConsentDate。它们实际上存在于扩展表中。

我不确定如何修改此xml以将这些字段指向Extension表 所以生成的查询实际上是从那个表而不是错误的表中提取它们。非常感谢任何帮助,这是我对NHiberate的第一次体验,不用说,这不是很有趣!

根据Frédéric的建议,我更新了但得到了这个错误:

NHibernate.dll中发生了'NHibernate.MappingException'类型的异常但未在用户代码中处理

其他信息:EdFi.Ods.Entities.NHibernate.Mappings.SqlServer.StudentProgramAssociationBase.hbm.xml(79,8):XML验证错误:名称空间'urn:nhibernate-mapping-2.2中的元素'joined-subclass' '在名称空间'urn:nhibernate-mapping-2.2'中有无效的子元素'join'。预期可能元素的列表:'属性,多对一,一对一,组件,动态组件,属性,任何,映射,集合,列表,包,idbag,数组,原始数组,连接子类,loader,sql-insert,sql-update,sql-delete,resultset,query,sql-query'innamespace'瓮:nhibernate-mapping-2.2'。

1 个答案:

答案 0 :(得分:1)

您的第二个表不应该映射为另一个joined-subclass,因为它与您的域模型中的子类不匹配。

应将其映射为独立的Extension实体,扩展实体将其引用为one-to-one相关实体。

或者您可以使用join映射在域模型中拥有单个实体。但join上不允许subclass映射,因此如果可以添加这些属性,则必须在基类上使用它。调整在注释中链接的pastebin映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   assembly="Entities.NHibernate" 
                   namespace="Entities.NHibernate.SPAssociationAggregate"
                           default-access="property">

  <!-- Class definition -->
  <class name="SPAssociationBase" table="SPAssociation" lazy="false">
    <!-- Composite primary key -->
    <composite-id>
      <key-property name="BeginDate" type="date" />
      <key-property name="OrganizationId" />
      <key-property name="ProgramOrganizationId" />
      <key-property name="ProgramName" length="60" />
      <key-property name="ProgramTypeId" />
      <key-property name="SUSI" />
    </composite-id>

    <!-- Optimistic locking for aggregate root -->
    <version name="LastModifiedDate" type="timestamp" />

    <!-- Transient state detection -->
    <property name="CreateDate" type="DateTime" />

    <!-- Unique Guid-based identifier for aggregate root -->
    <property name="Id" />

    <!-- Properties -->
    <property name="EndDate" type="date" />
    <property name="ReasonExitedDescriptorId" />
    <property name="ServedOutsideOfRegularSession" />

    <!-- Collections -->
    <bag name="SPAssociationServices" cascade="all-delete-orphan" inverse="true" lazy="false">
      <key>
        <column name="BeginDate" />
        <column name="OrganizationId" />
        <column name="ProgramOrganizationId" />
        <column name="ProgramName" />
        <column name="ProgramTypeId" />
        <column name="SUSI" />
      </key>
      <one-to-many class="SPAssociationServiceForBase" />
    </bag>

    <!-- Extended properties -->
    <join table="SSEPAssociationExtension" optional="true">
      <key>
        <column name="BeginDate" />
        <column name="OrganizationId" />
        <column name="ProgramOrganizationId" />
        <column name="ProgramName" />
        <column name="ProgramTypeId" />
        <column name="SUSI" />
      </key>
      <property name="EventCode" />
      <property name="WrittenConsentDate" />
    </join>

    <!-- Derived classes -->
    <joined-subclass name="SESProgramAssociationAggregate.SESProgramAssociation" table="SESProgramAssociation" lazy="false">
      <key>
        <column name="BeginDate" />
        <column name="OrganizationId" />
        <column name="ProgramOrganizationId" />
        <column name="ProgramName" />
        <column name="ProgramTypeId" />
        <column name="SUSI" />
      </key>

      <!-- Properties -->
      <property name="IdeaEligibility" />
      <property name="DescriptorId" />
      <property name="HoursPerWeek" />
      <property name="SHoursPerWeek" />
      <property name="MultiplyD" />
      <property name="MFragile" />
      <property name="LastEvaluationDate" type="date" />
      <property name="ReviewDate" type="date" />
      <property name="BeginDate" type="date" />
      <property name="EndDate" type="date" />
      <property name="EventCode" />
      <property name="WrittenConsentDate" type="date" />
    </joined-subclass>
  </class>
</hibernate-mapping>

附注:

  • 如果可能,最好避免使用复合键。或者将它们映射为component,为其覆盖GetHashCodeEquals,...
  • 如果列名相同,则无需复制属性名称。大多数属性类型都可以通过NHibernate从底层类推断出来。如果它们匹配,最好不要通过在映射中指定它们的类型来膨胀映射。 (所以我在上面的示例中只留下了字符串长度和日期类型,因为.Net日期和时间类型与SQL之间没有精确匹配。)
  • 将主键“重新映射”为子类中的属性很奇怪。您应该从基类<id>继承这些属性,因此您不需要在连接的子类中再次映射它们。
  • 禁用lazy加载不是NHibernate的惯常做法。使用NHibernate进行延迟加载可以获得批量加载,这使得它非常有效。有关详细信息,请参阅我的回答here 虽然使用复合键,但您应该将它们映射为最佳延迟加载的组件。 (否则,访问卸载的代理上的某个键属性将导致它加载。)