NHibernate - Mapeo de colecciones
En este capítulo, cubriremos cómo representar colecciones. Hay diferentes tipos de colecciones que podemos usar dentro de NHibernate como:
- Lists
- Sets
- Bags
Ahora, desde la perspectiva de .NET, generalmente tratamos con listas o como estructuras de datos muy simples, listas, diccionarios. .NET no tiene una amplia variedad de tipos de colecciones diferentes. Entonces, ¿por qué NHibernate necesita todos estos tipos diferentes? Realmente vuelve a la base de datos.
Lista
Una lista es una colección ordenada de elementos que no son necesariamente únicos.
Podemos mapear esto usando el IList <T>.
Entonces, aunque convencionalmente podríamos tener una lista de direcciones, y desde el punto de vista de la aplicación sabemos que los elementos son únicos, nada en la lista nos impide insertar elementos duplicados en esa lista.
Conjunto
Un conjunto es una colección desordenada de elementos únicos. Si intenta insertar 2 elementos duplicados en un conjunto, generará una excepción.
No hay nada específico en NHibernate al respecto.
Es solo una forma conveniente de tener una implementación de conjunto genérico. Si está en .NET 4, puede usar el nuevoHashSet <T> para representarlos, pero en la mayoría de las aplicaciones de NHibernate, representamos que se trata de un ISet.
No está ordenado, si extrae una lista de direcciones de una base de datos o una lista de pedidos, no sabe en qué orden vienen a menos que ingrese una cláusula específica de Orden por.
Entonces, en general, los datos que extrae de una base de datos son conjuntos.
Son colecciones únicas de elementos que no están ordenados.
Bolso
Otra colección común que veremos en el mundo de las bases de datos es una bolsa, que es como un conjunto, excepto que puede tener elementos duplicados.
En el mundo .NET, representamos esto mediante un IList.
Los conjuntos son probablemente los más comunes, pero también verá listas y bolsas según su aplicación. Echemos un vistazo a abajocustomer.hbm.xml Archivo del último capítulo en el que se definen las órdenes de 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>
Como puede ver, hemos mapeado la colección de pedidos como un conjunto. Recuerde que un conjunto es una colección desordenada de elementos únicos.
Ahora, si observa la clase Cliente, verá que la propiedad Pedidos está definida con un ISet como se muestra en el siguiente programa.
public virtual ISet<Order> Orders { get; set; }
Ahora, cuando se ejecute esta aplicación, verá el siguiente resultado.
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...
Si los elementos de la colección no necesitaban ser únicos, si pudiera tener varios pedidos con la misma clave principal que se produzcan varias veces en esta colección, entonces sería mejor mapearlo como una bolsa como se muestra en el siguiente programa.
<bag name = "Orders" table = "`Order`">
<key column = "CustomerId"/>
<one-to-many class = "Order"/>
</bag>
Ahora, si ejecuta esta aplicación obtendrá una excepción porque si echamos un vistazo a la clase de cliente, notará que los pedidos están marcados como ISet en el código C #.
Así que también tendremos que cambiar esto a un IList y luego aquí, necesitaríamos cambiar de HashSet a List en el constructor.
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();
}
}
Cuando ejecute la aplicación, verá el mismo comportamiento. Pero ahora podemos tener un orden que ocurre varias veces en la misma colección.
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...