NHibernate - 集合映射

在本章中,我们将介绍如何表示集合.我们可以在NHibernate中使用不同类型的集合,例如 :

  • 列表

  • 行李

现在,从.NET的角度来看,我们通常会处理列表或非常喜欢简单的数据结构,列表,词典. .NET没有各种不同的集合类型.那么为什么NHibernate需要所有这些不同的类型呢?它真的回到了数据库.

列表

  • 列表是一个有序的元素集合,不一定是唯一的.

  • 我们可以使用 IList< T> 来映射它.

  • 因此,虽然我们通常可能有一个地址列表,但从应用程序的角度来看,我们知道这些元素是唯一的,列表中的任何内容都不会阻止我们插入重复的元素在该列表中.

设置

  • 集合是一组无序的独特元素.如果你试图将2个重复的元素插入到一个集合中,它将抛出异常.

  • NHibernate中没有具体的内容.

  • 这只是一种方便的方式,有一个通用的集合实现.如果您使用的是.NET 4,则可以使用新的 HashSet< T> 来表示这些,但在大多数NHibernate应用程序中,我们表示这是一个ISet.

  • 这是一个无序的,如果您从数据库或订单列表中提取地址列表,您不知道他们将以什么顺序进入,除非您输入具体的订购条款.

  • 因此,一般来说,您从数据库中撤回的数据是设置的.

  • 它们是无序元素的唯一集合.

Bag

  • 我们将在数据库世界中看到的另一个常见集合是一个包,它就像一个集合,除了它可以有重复的元素.

  • 在.NET世界中,我们由IList代表.

套装可能是最常见的,但根据您的应用,您也会看到列表和包.让我们看一下下面 customer.hbm.xml 文件,该文件来自最后一章,其中定义了Set订单.

<?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>

如您所见,我们已将订单集合映射为一组.请记住,set是一个无序的唯一元素集合.

现在,如果查看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>

现在,如果您运行此应用程序,您将收到异常,因为如果我们查看客户类,您会注意到订单已标记作为C#代码中的ISet.

因此我们还需要将其更改为IList,然后在此处,我们需要在构造函数中将HashSet更改为List./p>

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...