NHibernate - 如何将composite-id映射到父子引用

时间:2011-03-30 12:56:16

标签: .net nhibernate parent-child composite-primary-key

我有以下场景(为了更好地说明,示例非常简化) Database Model BAS_COSTCODE是指BAS_CONTEXT。该表的关键是具有COSTCODEID和CONTEXT_FK的复合。 CONTEXT_FK指BAS_CONTEXT。 要构建分层树,CostCode可以具有父级。出于这个原因,可以参考表格itselfe。

Context的模式文件就是:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo" assembly="App.NHibernate.DataObjects" namespace="App.NHibernate.DataObjects">
      <class name="App.NHibernate.DataObjects.Context" table="BAS_CONTEXT" lazy="false" mutable="true" >
        <id name="Id" type="Int16" column="CONTEXTID" >
          <generator class="assigned"/>
        </id>
        <property name="Name" column="NAME" type="String" not-null="true"/>
       </class>
    </hibernate-mapping>

CostCode的架构就是这样:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" schema="dbo" assembly="App.NHibernate.DataObjects" namespace="App.NHibernate.DataObjects">
  <class name="App.NHibernate.DataObjects.CostCode" table="CON_COSTCODE" mutable="true" >

    <composite-id name="CompositeId" class="CostCodeId" unsaved-value="any">
      <key-property name="Id" column="COSTCODEID" type="String" />
      <key-many-to-one name="Context" column="CONTEXT_FK" class="Context" lazy="proxy"/>
    </composite-id>

    <many-to-one name="ParentCostCode" class="CostCode" lazy="proxy" insert="true" update="true" >
      <column name="PARENTCOSTCODE_FK"/>
      <column name="CONTEXT_FK"/>
    </many-to-one>

    <property name="Name" column="NAME" type="String"/>
  </class>
</hibernate-mapping>

如果我创建一个新的CostCode实体并运行Commit(),我会得到以下异常: System.IndexOutOfRangeException:“此SqlParameterCollection的索引13无效,Count = 13.”

我认为NHibernate的引用ParentCostCode存在问题,引用父CostCode对象。 NHIbernate假定将值写入列PARENTCOSTCODE_FK和CONTEXT_FK。在映射中,composite-id指向CONTEXT_FK,ParentCostCode指向CONTEXT_FK。所以他们“共享”相同的列,NHibernate只应该向PARENTCOSTCODE_FK列写一个值。

一种解决方案是向表BAS_COSTCODE添加一个额外的列(可能是PARENTCONTEXT_FK)来表示父对象的Context。 但是我不希望有一个额外的列,因为如果存在对父对象的引用,则CONTEXT_FK和PARENTCONTEXT_FK的值必须具有相同的值。这将是多余的。

这种问题有更好的解决方案吗?或者我无法阻止BAS_COSTCODE中的其他列?

非常感谢您的回答!

3 个答案:

答案 0 :(得分:0)

我们遇到了类似的问题,花了一些时间研究可能的解决方案。没有冗余列,我们找不到这样做的方法。它有点难看但你可以在模型类中加入一些逻辑来强制这两个值的一致性。

答案 1 :(得分:0)

我认为发生此错误是因为您有两次相同的列映射。 CONTEXT_FK

<many-to-one name="ParentCostCode" class="CostCode" lazy="proxy" insert="true" update="true" >
  <column name="PARENTCOSTCODE_FK"/>
  <column name="CONTEXT_FK"/>
</many-to-one>

您可能需要尝试此操作来解决它:

<many-to-one name="ParentCostCode" class="CostCode" lazy="proxy" insert="false" update="false">

答案 2 :(得分:0)

可以直接使用非复合键。

<id>
  <generator class="hilo">
     <!-- ... -->
  </generator>
</id>

<property name="CostCode" column="COSTCODEID" unique-key="CostCodeContext"/>

<many-to-one name="Context" >
  <column name="CONTEXT_FK" unique-key="CostCodeContext"> 
</many-to-one> 

<many-to-one name="Parent" class="CostCode">
  <column name="PARENT_FK"/>
</many-to-one>