这是我的实体关系模型的一部分:
我找到几种方法来映射'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搜索错过了答案。还有其他选择吗?
答案 0 :(得分:2)
在NHibernate中有两种主要的三元(a.k.a.三向)关联映射方式。
map
使用index-many-to-many
(a.k.a。map-key-many-to-many
)和composite-element
内容收集。<小时/>
map
使用index-many-to-many
有两种可能的方法来映射三元关联。一种方法是使用复合元素(下面讨论)。另一种方法是使用带有关联的
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>
,因为它是不可变的 - 属性Item1
和Item2
没有设置者。但为此目的创建一个具有两个属性的小类是微不足道的。