我们有一个我们无法改变的遗留数据库。我们正试图转移到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>
BLOCK
<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>
COMPANY
<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方法。
以下是有效的导航器列表:
这两个失败了:
我有一个单元测试:
[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映射测试中的块导航映射并输出一些数据:
Block#1
公司'LALA':
公司'LALA SA':
块#2
公司'BG PO':
公司'LIMPOPO':
Block#3
公司'哈哈':
公司'其他合作伙伴':
Block#4
但是测试失败并出现以下错误:
NHibernate.LazyInitializationException:正在初始化[Model.EntityClasses.Block#999] - 无法初始化角色集合:Model.EntityClasses.Block.GroupPartnerInterests,没有关闭会话或会话。
'999'是现有的PAR_ID - 数据是一致的:这个PAR_ID有两个块,GPI有几个记录。
为什么会在某个时候关闭会话?
单元测试与我上面提到的几乎相同,只是使用了不同的属性。 错误如下:
NHibernate.MappingException:NHibernate.MappingException:找不到属性:实体Model.EntityClasses.GroupPartnerInterest上的GroupId。
如果我从GPI映射中的Blocks导航器元素中删除“property-ref = GroupId”,我将得到以下异常:
NHibernate.FKUnmatchingColumnsException:NHibernate.FKUnmatchingColumnsException:外键(FKA3966498349694F:[BLOCK] [PAR_ID]))必须与引用的主键([GPI] [PAR_ID,PU_ID])具有相同的列数。
有没有办法将块映射到GPI,以便GroupPartnerInterest.Blocks导航器可以工作?
谢谢, 亚历
答案 0 :(得分:2)
问题如下:
GroupPartnerInterest
中的阻止是一个集合,因此外键位于Blocks
,指向GroupPartnerInterest
。这将需要两个外键,这些外键不可用。property-ref
是用其他属性替换主键。因此,它是关系一侧的表的属性,GroupPartnerInterest
,但没有GroupId
。property-ref
使用GroupPartnerInterest.Blocks
(因为缺少两个外键,使Block.PAR_ID
指向GPI.PAR_ID
),但我会三思而后行。我不能在这里给你一个有效的解决方案。我不使用复合键,这更复杂。但还有一些想法:
为什么会话结束?我不知道,我会看看堆栈跟踪。它是从使用块中真正抛出的异常吗?或者它是从TestCleanup
方法抛出的?