- NHibernate 教程
- NHibernate - 首頁
- NHibernate - 概述
- NHibernate - 架構
- NHibernate - ORM
- NHibernate - 環境設定
- NHibernate - 快速入門
- NHibernate - 基礎ORM
- NHibernate - 基本CRUD操作
- NHibernate - 效能分析器
- 為對映檔案新增IntelliSense
- NHibernate - 資料型別對映
- NHibernate - 配置
- NHibernate - 覆蓋配置
- NHibernate - 批處理大小
- NHibernate - 快取
- NHibernate - 元件對映
- NHibernate - 關係
- NHibernate - 集合對映
- NHibernate - 級聯操作
- NHibernate - 延遲載入
- NHibernate - 反向關係
- NHibernate - Load/Get
- NHibernate - LINQ
- NHibernate - 查詢語言 (HQL)
- NHibernate - Criteria 查詢
- NHibernate - QueryOver 查詢
- NHibernate - 原生SQL
- NHibernate - Fluent NHibernate
- NHibernate 有用資源
- NHibernate - 快速指南
- NHibernate - 有用資源
- NHibernate - 討論
NHibernate - 集合對映
本章將介紹如何表示集合。NHibernate 中可以使用不同型別的集合,例如:
- 列表 (Lists)
- 集合 (Sets)
- 包 (Bags)
從 .NET 的角度來看,我們通常處理列表或非常簡單的列表、字典等資料結構。.NET 沒有各種各樣的集合型別。那麼,為什麼 NHibernate 需要所有這些不同型別呢?這實際上與資料庫有關。
列表 (List)
列表是有序的元素集合,這些元素不一定是唯一的。
我們可以使用IList <T> 來對映它。
因此,儘管我們通常可能有一個地址列表,並且從應用程式的角度來看,我們知道這些元素是唯一的,但列表中沒有任何內容可以阻止我們向該列表中插入重複元素。
集合 (Set)
集合是唯一元素的無序集合。如果您嘗試將兩個重複的元素插入集合中,它將丟擲異常。
NHibernate 中沒有關於它的具體內容。
這只是擁有泛型集合實現的一種便捷方式。如果您使用的是 .NET 4,可以使用新的HashSet <T> 來表示這些,但在大多數 NHibernate 應用程式中,我們將其表示為 ISet。
它是無序的,如果您從資料庫中提取地址列表或訂單列表,除非您新增特定的 Order by 子句,否則您不知道它們的順序。
因此,一般來說,您從資料庫中提取的資料是集合。
它們是唯一元素的無序集合。
包 (Bag)
我們在資料庫世界中看到的另一個常見集合是包,它與集合類似,只是它可以包含重複元素。
在 .NET 世界中,我們透過 IList 來表示它。
集合可能是最常見的,但是根據您的應用程式,您也會看到列表和包。讓我們看一下上一章中定義了 Set 訂單的customer.hbm.xml 檔案。
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
namespace = "NHibernateDemo">
<class name = "Customer">
<id name = "Id">
<generator class = "guid.comb"/>
</id>
<property name = "FirstName"/>
<property name = "LastName"/>
<property name = "AverageRating"/>
<property name = "Points"/>
<property name = "HasGoldStatus"/>
<property name = "MemberSince" type = "UtcDateTime"/>
<property name = "CreditRating" type = "CustomerCreditRatingType"/>
<component name = "Address">
<property name = "Street"/>
<property name = "City"/>
<property name = "Province"/>
<property name = "Country"/>
</component>
<set name = "Orders" table = "`Order`">
<key column = "CustomerId"/>
<one-to-many class = "Order"/>
</set>
</class>
</hibernate-mapping>
如您所見,我們已將 orders 集合對映為一個集合。請記住,集合是唯一元素的無序集合。
現在,如果您檢視 Customer 類,您會看到 Orders 屬性是用 ISet 定義的,如下面的程式所示。
public virtual ISet<Order> Orders { get; set; }
現在執行此應用程式時,您將看到以下輸出。
New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Order Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
The orders were ordered by:
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
John Doe (1f248133-b50a-4ad7-9915-a5b8017d0ff1)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: c41af8f2-7124-42a7-91c5-a5b8017d0ff6
Order Id: 657f6bb0-1f42-45fc-8fc7-a5b8017d0ff7
Press <ENTER> to exit...
如果集合中的專案不需要唯一,如果您可以在此集合中多次出現具有相同主鍵的多個訂單,那麼最好將其對映為包,如下面的程式所示。
<bag name = "Orders" table = "`Order`"> <key column = "CustomerId"/> <one-to-many class = "Order"/> </bag>
現在,如果您執行此應用程式,您將收到一個異常,因為如果我們檢視 customer 類,您會注意到訂單在 C# 程式碼中被標記為 ISet。
因此,我們還需要將其更改為 IList,然後在這裡,我們需要將建構函式中的 HashSet 更改為 List。
public class Customer {
public Customer() {
MemberSince = DateTime.UtcNow;
Orders = new List<Order>();
}
public virtual Guid Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual double AverageRating { get; set; }
public virtual int Points { get; set; }
public virtual bool HasGoldStatus { get; set; }
public virtual DateTime MemberSince { get; set; }
public virtual CustomerCreditRating CreditRating { get; set; }
public virtual Location Address { get; set; }
public virtual IList<Order> Orders { get; set; }
public virtual void AddOrder(Order order) { Orders.Add(order); order.Customer = this; }
public override string ToString() {
var result = new StringBuilder();
result.AppendFormat("{1} {2} ({0})\r\n\tPoints: {3}\r\n\tHasGoldStatus:
{4}\r\n\tMemberSince: {5} ({7})\r\n\tCreditRating: {6}\r\n\tAverageRating:
{8}\r\n", Id, FirstName, LastName, Points, HasGoldStatus, MemberSince,
CreditRating, MemberSince.Kind, AverageRating); result.AppendLine("\tOrders:");
foreach(var order in Orders) {
result.AppendLine("\t\t" + order);
}
return result.ToString();
}
}
執行應用程式時,您將看到相同的行為。但是,現在我們可以讓同一個集合中出現多個訂單。
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Order Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
The orders were ordered by:
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
John Doe (fbde48f5-d620-4d1c-9a7f-a5b8017c3280)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: 6dd7dbdb-354f-4c82-9c39-a5b8017c3286
Order Id: 9b3e2441-a81b-404d-9aed-a5b8017c3287
Press <ENTER> to exit...