NHibernate - Отображение коллекции

В этой главе мы рассмотрим, как представлять коллекции. Существуют различные типы коллекций, которые мы можем использовать в NHibernate, такие как -

  • Lists
  • Sets
  • Bags

Теперь, с точки зрения .NET, мы обычно имеем дело со списками или подобными очень простыми структурами данных, списками, словарями. .NET не имеет большого разнообразия различных типов коллекций. Итак, зачем NHibernate все эти разные типы? Это действительно возвращается в базу данных.

Список

  • Список - это упорядоченный набор элементов, которые не обязательно уникальны.

  • Мы можем отобразить это, используя IList <T>.

  • Таким образом, хотя мы можем условно иметь список адресов и с точки зрения приложения мы знаем, что элементы уникальны, ничто в списке не мешает нам вставлять повторяющиеся элементы в этот список.

Набор

  • Набор - это неупорядоченный набор уникальных элементов. Если вы попытаетесь вставить 2 повторяющихся элемента в набор, это вызовет исключение.

  • В NHibernate нет ничего особенного.

  • Это просто удобный способ реализации общего набора. Если вы используете .NET 4, вы можете использовать новыйHashSet <T> чтобы представить их, но в большинстве приложений NHibernate мы представляем, что это ISet.

  • Он неупорядоченный: если вы извлечете список адресов из базы данных или список заказов, вы не узнаете, в каком порядке они поступают, если только вы не укажете конкретное предложение Order by.

  • В общем, данные, которые вы извлекаете из базы данных, являются наборами.

  • Это уникальные неупорядоченные коллекции элементов.

Сумка

  • Еще одна распространенная коллекция, которую мы увидим в мире баз данных, - это сумка, которая похожа на набор, но может иметь повторяющиеся элементы.

  • В мире .NET мы представляем это с помощью IList.

Наборы, вероятно, самые распространенные, но вы также увидите списки и пакеты в зависимости от вашего приложения. Давайте посмотрим на нижеприведенный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>

Как видите, мы сопоставили коллекцию заказов как набор. Помните, что набор - это неупорядоченный набор уникальных элементов.

Теперь, если вы посмотрите на класс 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>

Теперь, если вы запустите это приложение, вы получите исключение, потому что, если мы посмотрим на класс клиента, вы заметите, что заказы помечены как ISet в коде C #.

Так что нам также нужно будет изменить это на 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...