多个实体关系映射流畅的NHibernate

时间:2013-11-11 19:12:32

标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping

这是我的实体关系模型的一部分:

ER diagram

我找到几种方法来映射'It'关系:
One :添加新课程,然后使用多对多关系引用它:

class It{
  A a;
  B b;
  C c;
}
class A{
  public virtual ISet<It> Relationship{set;get;}
}

但是,我担心NHibernate可能会自己为'It'添加一个ID,或者我可能需要使用复合键(这不是一个好习惯)。

两个:我找到了this。它在每个类上使用两个单独的集合来建模三向关系。但我认为以后会有不必要的工作来访问这些信息,而且使映射正确起来有点麻烦。

相反,我认为我可以做类似的事情:

class A{
  IList<Tuple<C, D>> ARelationship;
}

这样你从头开始就有两个引用。但是我还没有找到关于如何进行这种映射的示例(元组列表)。我发现你可以定义一个ICompositeUserType子类来做到这一点,但我不完全理解它是如何工作的或如何使用它来解决我的问题。

我的问题(s)是:建立这种关系的最佳方式是什么?
如果是通过使用单独的类(方法一),从每个类的角度映射它的最佳方法是什么,以及如何映射新定义的类?
如果是使用元组列表,是否可以在不使用ICompositeUserType的情况下映射它?怎么样?
此外,我可能通过不正确的Google搜索错过了答案。还有其他选择吗?

1 个答案:

答案 0 :(得分:2)

NHibernate中的三向关联

在NHibernate中有两种主要的三元(a.k.a.三向)关联映射方式。

  1. map使用index-many-to-many(a.k.a。map-key-many-to-many)和
  2. 使用composite-element内容收集。
  3. <小时/>

    map使用index-many-to-many

    来自documentation

      

    有两种可能的方法来映射三元关联。一种方法是使用复合元素(下面讨论)。另一种方法是使用带有关联的IDictionary作为其索引:

    <map name="Contracts" lazy="true">
        <key column="employer_id"/>
        <index-many-to-many column="employee_id" class="Employee"/>
        <one-to-many class="Contract"/>
    </map>
    
    <map name="Connections" lazy="true">
        <key column="node1_id"/>
        <index-many-to-many column="node2_id" class="Node"/>
        <many-to-many column="connection_id" class="Connection"/>
    </map>
    

    如果可能,我喜欢使用上图所示的IDictionary方法。当关联表中的两个引用存在某种唯一约束时,这种方法非常适合,如下所示:

    create table It (
        A_id int not null,
        B_id int not null,
        C_id int not null,
        primary key (A_id, B_id),
        foreign key (A_id) references A (Id),
        foreign key (B_id) references B (Id),
        foreign key (C_id) references C (Id)
    );
    

    这允许您创建一个看起来像这样的对象模型:

    public class A
    {
        public virtual IDictionary<B, C> RelatedCEntities { get; set; }
    }
    

    此映射看起来像:

    <map name="RelatedCEntities" table="It">
        <key column="A_id"/>
        <index-many-to-many column="B_id" class="B"/>
        <many-to-many column="C_id" class="C"/>
    </map>
    

    您永远不必将It映射为实体。它只是用作many-to-many的关联表。


    带有composite-element

    集合

    如果没有唯一约束,我们可以查看a little lower in the documentation复合元素:

      

    支持组件集合(例如,类型为Name的数组)。通过将<element>标记替换为<composite-element>标记来声明您的组件集合。

    <set name="SomeNames" table="some_names" lazy="true">
        <key column="id"/>
        <composite-element class="Eg.Name, Eg"> <!-- class attribute required -->
            <property name="Initial"/>
            <property name="First"/>
            <property name="Last"/>
        </composite-element>
    </set>
    
         

    注意:如果您定义了ISet个复合元素,那么正确实施Equals()GetHashCode()非常重要。

         

    ...

         

    即使是三元(或四元等)关联也是可能的:

    <class name="Order" .... >
        ....
        <set name="PurchasedItems" table="purchase_items" lazy="true">
            <key column="order_id">
            <composite-element class="OrderLine">
                <many-to-one name="PurchaseDetails class="Purchase"/>
                <many-to-one name="Item" class="Item"/>
            </composite-element>
        </set>
    </class>
    

    我认为您无法使用Tuple<T1, T2>,因为它是不可变的 - 属性Item1Item2没有设置者。但为此目的创建一个具有两个属性的小类是微不足道的。