使用 Fluent NHibernate 和 AsList() 时指定主键

Posted

技术标签:

【中文标题】使用 Fluent NHibernate 和 AsList() 时指定主键【英文标题】:Specifying the Primary Key when using Fluent NHibernate and AsList() 【发布时间】:2012-12-11 16:38:01 【问题描述】:

我有一个场景,其中一个用户实体有一个国家 ID 列表,保存为 IList。

public virtual IList<int> TradeCountries  get; protected set; 

目前这被映射为

HasMany(x => x.TradeCountries).Element("TradeCountryId").AsList(x => x.Column("TradeCountryIndex"));

结果表是这样定义的

create table TradeCountries (
    User_id INT not null,
   TradeCountryId INT null,
   TradeCountryIndex INT not null,
   primary key (User_id, TradeCountryIndex)
)

这一切都很好 - 但是我想让 TradeCountries 上的 PK 成为 User_id,TradeCountryId。使用 AsList() 进行映射时,我似乎找不到这样做的方法。有什么想法吗?

【问题讨论】:

您希望您的主键包含两个字段吗? (User_id 和 TradeCounryId) PK为什么要TradeCountryId?唯一性约束? NHibernate 在 PK 中使用索引,因为这对 NH 很重要。你真的需要在集合中存储每个国家的位置吗? @OskarBerggren 我想将其映射为一个列表,只是为了避免我在将组件映射为集合或包时遇到的“全部删除/重新插入”行为 嗯...我不希望您使用集合获得 delete-all-reinsert - 因为元素是唯一的,所以所有者引用和元素值/id 形成一个唯一键,它启用针对单个行。要启用此功能,您必须为元素指定 not-null="true",但不幸的是,文档中似乎缺少此功能,并且未在 Fluent NHibernate 中公开(尽管添加它可能相当容易)。无论如何,还有idbag可以防止此类问题。 【参考方案1】:

Fluent NHibernate 中使用的集合的转换是这样进行(as described here) 的:

// <set>
public virtual ISet<Child> Children  get; set;     
HasMany(x => x.Children); // <set />

// <bag>
public virtual IList<Child> Children  get; set;     
HasMany(x => x.Children); // <bag />

// <list>
public virtual IList<Child> Children  get; set;     
HasMany(x => x.Children).AsList(...; // <list />

这些映射的本质/区别在文档Understanding Collection performance 和Ayende's post: &lt;list&gt;) 中有详细描述。 提取

...虽然&lt;set/&gt; 是一个无序集合,具有独特元素,但&lt;list/&gt; 是顺序很重要的元素的集合,并且重复 允许元素...

换句话说,当使用&lt;list&gt; 时,您必须在 keyindex 列上保留 PK,因为可能存在重复。

在您的情况下,仅&lt;bag&gt; 映射(没有明确的.AsList() 调用)就足够高效了,您可以删除索引列,并将PK 移动到 keyelement (User_id, TradeCountryId)。

注意:C# IList 仍然允许有更多“相同”的元素,你应该在业务层检查它

【讨论】:

以上是关于使用 Fluent NHibernate 和 AsList() 时指定主键的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Fluent-NHibernate 和 MySQL 指定自动递增 (int) 标识列

如何使用 Fluent 设置 NHibernate.Burrow?

NHibernate 2 + Fluent Nhibernate 中等信任

使用 Fluent NHibernate 和 AsList() 时指定主键

Fluent NHibernate使用我的用户名作为前缀创建表

Castle Windsor 3 + Fluent NHibernate + Castle.NHibernate.Integration