我们有一个我们无法更改的遗留数据库。我们正在尝试移植到NHibernate,而不是旧的DataAccess层,这是一个垃圾,而且太慢了。将NHibernate导航器映射到组合键问题的一部分 - 遗留数据库的使用
它具有这样的表:
GPI表具有(PU_ID,PAR_ID,数据,数据2)个列
BLOCK表具有(GA_ID,数据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>
公司
<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.GroupPartnerInterests:
我有一个单元测试:
[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
Company 'LALA':
Company 'LALA SA':
Block #2
Company 'BG PO':
Company 'LIMPOPO':
Block #3
Company 'HAHA':
Company 'Other partner(s)':
Block #4
但测试失败,出现以下错误:
NHibernate.LazyInitializationException: Initializing[Model.EntityClasses.Block#999]-failed to lazily initialize a collection of role: Model.EntityClasses.Block.GroupPartnerInterests, no session or session was closed.
'999'是现有的PAR_ID - 数据是一致的:在GPI中有两个包含此PAR_ID和几条记录的块。
为什么它在某个时候关闭会话?
- GroupPartnerInterest.Blocks:
单元测试是如我上面提到的,只是不同的属性用于几乎相同。下面 错误是:
NHibernate.MappingException: NHibernate.MappingException: property not found: GroupId on entity Model.EntityClasses.GroupPartnerInterest.
如果我删除“属性-REF = GroupId的”从块导航在GPI映射元素,我会出现以下情况例外:
NHibernate.FKUnmatchingColumnsException: NHibernate.FKUnmatchingColumnsException: Foreign key (FKA3966498349694F:[BLOCK] [PAR_ID])) must have same number of columns as the referenced primary key ([GPI] [PAR_ID, PU_ID]).
是有没有办法将Blocks映射到GPI,这样GroupPartnerInterest.Blocks导航器就可以工作了?
谢谢, 亚历克斯
谢谢您的深入解答! 我将尝试说服我们的团队领导改变数据库架构,只需添加一个自动生成(增量)主键到GPI表。 这将修复property-ref = GroupId问题,并应修复我的问题导航属性 – LucID 2010-08-27 09:24:33
我有一个非常类似的问题。我试图用xml和流利的映射来映射这个场景,但没有喜悦。不幸的是,我现在无法改变模式。我可以让你看看吗? http://stackoverflow.com/questions/25191275/fluent-nhibernate-map-hasmany-to-entity-table-with-no-primary-key – 2014-08-08 15:09:35