2

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

ER图

我发现了几种映射“It”关系的方法:
一种:添加新类,然后使用多对多关系引用它:

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

但是,我担心 NHibernate 可能会自行向“It”添加一个 ID,或者我可能不得不使用复合键(这不是一个好习惯)。

:我找到了这个。它在每个类上使用两个单独的集合来建模三向关系。但我认为以后访问信息会付出不必要的努力,而且要正确映射有点棘手。

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

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

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

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

4

1 回答 1

2

NHibernate 中的三向关联

在 NHibernate 中有两种主要的映射三元(又称三元)关联的方法。

  1. map使用index-many-to-many(又名map-key-many-to-many),和
  2. composite-element与内容的集合。


map使用index-many-to-many

文档中:

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

<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

如果没有唯一约束,我们可以在复合元素的文档中看起来更低一些:

支持组件的集合(例如 type 的数组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>,因为它是不可变的 - 属性Item1并且Item2没有设置器。但是为此目的创建一个具有两个属性的小类是微不足道的。

于 2013-11-11T20:26:19.267 回答