關係映射是 NHibernate 核心亮點亦是難點。本文從集合類型認知入手,構建 Customer-Order 經典一對多父子關係,奠定後續關聯查詢、加載機制探討基礎。
| 集合類型 | 特性 | .NET 對應 | 適用場景 |
|---|---|---|---|
| Bag | 允許重複、無序 | IList / IList<T> | 一般列表、允許重複業務 |
| Set | 唯一、無序 | ISet / ISet<T> (Iesi.Collections) | 最貼近關係模型、推薦首選 |
| List | 有序、允許重複、索引訪問 | ArrayList / List<T> | 需保持順序的集合 |
| Map | 鍵值對 | Hashtable / IDictionary<TKey,TValue> | 字典式訪問 |
實務建議:優先使用 Set,語義最清晰且與資料庫集合論一致。
Customer(父)1∶N Order(子),資料庫外鍵 Customer 在 Order 表中。
using Iesi.Collections.Generic;
namespace DomainModel.Entities
{
public class Customer
{
public virtual int CustomerId { get; set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
// 一對多:使用 ISet 保證唯一性
public virtual ISet<Order> Orders { get; set; }
}
}
namespace DomainModel.Entities
{
public class Order
{
public virtual int OrderId { get; set; }
public virtual DateTime OrderDate { get; set; }
// 多對一:引用父對象
public virtual Customer Customer { get; set; }
}
}
<class name="DomainModel.Entities.Customer,DomainModel" table="Customer">
<id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="Firstname" column="Firstname" type="string" length="50" />
<property name="Lastname" column="Lastname" type="string" length="50" />
<!-- 一對多:Set 集合,inverse=true 由子端維護關係 -->
<set name="Orders" table="`Order`" generic="true" inverse="true">
<key column="Customer" foreign-key="FK_CustomerOrders"/>
<one-to-many class="DomainModel.Entities.Order,DomainModel"/>
</set>
</class>
inverse="true":關鍵設置!聲明關係由 子端 維護,避免 NHibernate 執行額外 UPDATE 同步外鍵table="`Order`":指定子表名(Order 為保留字需轉義)key column="Customer":子表中外鍵欄位名generic="true":啟用泛型集合<class name="DomainModel.Entities.Order,DomainModel" table="`Order`">
<id name="OrderId" column="OrderId" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="OrderDate" column="OrderDate" type="DateTime" not-null="true" />
<!-- 多對一:指向父端 -->
<many-to-one name="Customer" column="Customer" not-null="true"
class="DomainModel.Entities.Customer,DomainModel"
foreign-key="FK_CustomerOrders" />
</class>
| 屬性 | 默認值 | 說明 |
|---|---|---|
| cascade | none | 級聯行為:all/save-update/delete/none |
| fetch | select | select=單獨查詢、join=外連接抓取 |
| lazy | proxy | proxy=代理延遲、false=立即加載 |
| not-null | false | 外鍵是否非空 |
| foreign-key | - | DDL 生成外鍵名稱 |
customer.Orders[...](集合)、order.Customer(單一引用)inverse="true" 將責任交給 Order 端,插入 Order 時自動設置外鍵set 或 many-to-one 配置 cascade 控制保存/刪除傳播一對多映射核心三要素:
Set/Bag + one-to-many + inverse="true"many-to-one 引用父端掌握此模式,即可構建任意層級的父子關係。下篇將基於此映射展開三大查詢方式實戰。