我们有一个无法更改的旧数据库。而且我们正在尝试迁移到NHibernate而不是旧的DataAccess层,这是一个垃圾,太慢了。

它具有如下表:

GPI表具有(PU_ID,PAR_ID,Data,Data2)列
BLOCK表具有(GA_ID,Data,PAR_ID)列
COMPANY表具有(PU_ID,数据)列

我已经为上面的表创建了这些映射:

GPI

<class name="GroupPartnerInterest" table="[GPI]">
    <composite-id >
        <key-property name="GroupId" column="PAR_ID" />
        <key-property name="CompanyId" column="PU_ID" />
    </composite-id>
    <property name="data" column="Data"/>
    <property name="data2" column="Data2"/>
    <many-to-one name="Company" fetch="select" cascade="none">
        <column name="PU_ID"/>
    </many-to-one>
    <set name="Blocks" cascade="none" inverse="true" fetch="select">
        <key property-ref="GroupId">
            <column name="PAR_ID"/>
        </key>
        <one-to-many class="Block"/>
    </set>
</class>

堵塞
<class name="Block" table="[BLOCK]" >
    <id name="BlockId" column="GA_ID" >
        <generator class="assigned"/>
    </id>
    <property name="data" column="Data"/>
    <property name="GroupId" column="PAR_ID"/>
    <set name="GroupPartnerInterests" cascade="all-delete-orphan" fetch="select">
        <key property-ref="GroupId">
            <column name="PAR_ID"/>
        </key>
        <one-to-many class="GroupPartnerInterest"/>
    </set>
</class>

公司
<class name="Company" table="[COMPANY]">
    <id name="CompanyId" column="PU_ID">
        <generator class="assigned"/>
    </id>
    <property name="data" column="Data"/>
    <set name="GroupPartnerInterests" cascade="none" inverse="true" fetch="select">
        <key>
            <column name="PU_ID"/>
        </key>
        <one-to-many class="GroupPartnerInterest"/>
    </set>
</class>

这些类非常简单明了。全部实现Equals和GetHashCode方法。

以下是适用的导航器列表:
  • GroupPartnerInterest.Company-伟大的
  • Company.GroupPartnerInterests-很棒的
  • GroupPartnerInterest.Company-伟大的

  • 而这两个失败:
  • Block.GroupPartner兴趣:

  • 我有一个单元测试:
    [TestMethod]
    public void TestGroupPartnerInterests()
    {
        using ( ISession session = SessionFactory.OpenSession() )
        {
            IList<Block> blocks = session.CreateCriteria( typeof( Block ) )
                .SetMaxResults( 5 ).List<Block>();
    
            foreach ( var block in blocks )
            {
                TestContext.WriteLine( "Block #{0}", block.BlockId );
    
                if ( block.GroupPartnerInterests != null )
                {
                    foreach ( GroupPartnerInterest gpi in block.GroupPartnerInterests )
                    {
                        TestContext.WriteLine( "Company '{0}':", gpi.Company.CompanyId );
                    }
                }
            }
        }
    }
    

    如果我注释掉了GPI映射测试中的Blocks导航映射,并且输出了一些数据:



    但是测试失败,并显示以下错误:



    “999”是现有的PAR_ID-数据是一致的:此PAR_ID有两个块,GPI中有一些记录。

    为什么有时会关闭 session ?
  • GroupPartnerInterest.Blocks:

  • 单元测试与我上面提到的几乎相同,只是使用了不同的属性。
    错误如下:



    如果从GPI映射中的“块”导航器的元素中删除“property-ref = GroupId”,我将得到以下异常:



    有什么方法可以将Block映射到GPI,以便GroupPartnerInterest.Blocks导航器可以工作?

    谢谢,
    亚历克斯

    最佳答案

    问题如下:

  • 如果您的实体包含复合 Material
    id,所有对它的引用都必须
    维护复合ID,因此
    必须是两个外键。
  • GroupPartnerInterest中的块是一个集合,因此外键位于Blocks中,指向GroupPartnerInterest。这将需要两个外键,这些外键不可用。
  • property-ref将主键替换为其他属性。因此,它是表在关系的一侧的属性,即GroupPartnerInterest,但没有GroupId
  • 您可能可以将property-ref用作GroupPartnerInterest.Blocks(因为缺少两个外键,以使Block.PAR_ID指向GPI.PAR_ID),但是我会三思而后行。

  • 我无法在这里为您提供有效的解决方案。我不使用复合键,这更复杂。但是还有更多的想法:
  • 我将尝试避免使用复合键。如果不可能,请编写一个代表组合键的类。这使得处理起来更加容易。
  • 我将尝试避免不基于主键的关系。可能有其他原因,NH支持他们,我只是认为它们会引起麻烦。


  • 为什么 session 关闭?我不知道,我将看一下堆栈跟踪。真的是在using块内抛出了异常吗?还是从TestCleanup方法抛出?

    关于NHibernate导航器映射到组合键问题的一部分-旧版数据库用法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3537021/

    10-11 18:24