So far, we've shown how to use collections where an entity relates to a set of other entitities. However, a collection can also hold simple values, such as strings or components, that is, objects with properties but no id.
ComponentCollections
to the MappingRecipes
project.Customer
to the folder:public class Customer { public Customer() { Addresses=new List<Address>(); Tags=new HashSet<string>(); } public virtual Guid Id { get; protected set; } public virtual string Name { get; set; } public virtual IList<Address> Addresses { get; set; } public virtual ISet<string> Tags { get; set; } }
Address
to the folder:public class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public string City { get; set; } public string PostalCode { get; set; } }
Customer.hbm.xml
to the folder:<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MappingRecipes" namespace="MappingRecipes.ComponentCollections"> <class name="Customer"> <id name="Id"> <generator class="guid.comb"/> </id> <property name="Name"/> <list name="Addresses" table="CustomerAddress"> <key column="CustomerId"/> <index column="AddressIndex"/> <composite-element class="Address"> <property name="AddressLine1"/> <property name="AddressLine2"/> <property name="City"/> <property name="PostalCode"/> </composite-element> </list> <set name="Tags" table="CustomerTag"> <key column="CustomerId"/> <element column="Tag" type="string"/> </set> </class> </hibernate-mapping>
Recipe
to the folder:using NH4CookbookHelpers; using NHibernate; namespace MappingRecipes.ComponentCollections { public class Recipe : HbmMappingRecipe { protected override void AddInitialData(ISession session) { session.Save(new Customer { Name = "Max Weinberg", Addresses = { new Address { AddressLine1 = "E Street 1", City = "Belmar, NJ" }, new Address { AddressLine1 = "Home street", City = "Newark, NJ" } }, Tags = { "Drummer", "Bruce" } }); } } }
ComponentCollections
recipe. The query log will look similar to this:Mapping a collection of simple values or components is very similar to mapping a collection of entities. We can use the same type of collections - bags, lists, and sets - following the same rules regarding duplicates and ordering.
Since this kind of collection always is implicitly one-to-many, we cannot specify that in the mapping. Instead, we use composite-element
for components, specifying the included component properties, or element for simple values. Both require that we specify a separate table where the values should be persisted.
Similar to how it is with the entity collections, a set
mapping requires working overrides of Equals
and GetHashCode
to function properly. Simple value types, such as string, provide this by default. Components, such as Address
, require a unique implementation.
The component collections mapped using composite-element
may look similar to component
properties and they are; however, there are a few differences.
A component in a composite-element
mapping can contain other nested components that should be specified using a nested-composite-element
tag. However, unlike component properties, they cannot contain collections. The reason for this is simply that all collection relationships require some kind of Id on the parent side and components don't provide this.
18.225.255.86