使用Foreign Key to Foreign key映射一个到多个集合

时间:2009-02-08 03:23:54

标签: nhibernate nhibernate-mapping legacy-database

我正在使用nhibernate映射遗留数据库,并且在映射关系时遇到一些问题。

这两个类看起来像这样

public class Questionnaire
{
    public int Id {get; set;}
    public string FormCode {get; set;}
    public IList<Question> Questions {get; set;}
}

public class Question
{
    public int Id{get; set;}
    public Questionnaire Questionnaire {get;set;}
    public string QuestionText{get;set;}
}

到这样的表

Questionnaire Table  
Id int  
FormCode varchar(100)  

Question Table  
Id int  
FormCode varchar(100)  
QuestionText varchar(max)  

两个表之间的关系是formcode列。

我当前的映射就像这样

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="QDesign.Core.Models" assembly="QDesign.Core">
<class name="Questionnaire" table="_questionnaire_list">
    <id column="Id" name="Id">
            <generator class="identity"/>
    </id>
        <property name="FormCode" column="FormCode"/>
        <bag name="Questions" >
            <key foreign-key="FormCode" property-ref="FormCode" />
            <one-to-many class="Question" />            
        </bag>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="QDesign.Core.Models" assembly="QDesign.Core">
<class name="Question" table="_questionnaire_items">
    <id column="ID" name="Id" unsaved-value="-1">
            <generator class="identity" />
        </id>
        <property name="QuestionText" column="QuestionText" />
</class>
</hibernate-mapping>

当我运行映射时,我得到一个标识符类型不匹配,假设它试图将表单代码放入问题的Id中。不幸的是我无法改变表格的结构,我对如何映射这一点感到茫然,我们将非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

您的关系是m:n关系,没有中间实体。以这种方式定义m:n关系是一个经典的错误,因为它会切出一个pk端,这会导致两个表具有相同属性/字段的情况,并且它们恰好在语义上代表相同的事物。但是,因为它们在双方都是非pk值,所以存在冗余并且还可能存在不准确性。您可以在两个字段上将两个表连接在一起,但在语义上它没有任何意义:对于将实体X与Y关联的实体模型,FK端将关系的PK侧作为FK字段获取,对于m:n关系,您需要两个m:1关系来自中间实体。那是,也不例外。

因此,虽然你想以你的方式映射这个,但是由于o / r映射器无法保证正确性,因此无法完成,因为建议的关系根本不正确。

答案 1 :(得分:2)

这是ORM的“问题”。我说“问题”是因为Hibernate在技术上是正确的:外键应该是主键。但是,正如你所见,情况并非总是如此。

ID实际上是用于什么吗?如果不是,阻力最小的路径是使FormCode成为主键。这是一个选择吗?

如果没有,除了查询问题而不是将它们视为子实体之外,我真的不确定该做什么。