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...
廣告
© . All rights reserved.