6. Advanced mapping concept
6.1 Understanding the NHibernate type system
Entities are the coarse-grained classes in a system.
value types are the much more fine-grained classes in a system
An entity is any class whose instances have their own persistent identity, and a value type is a class whose instance don't.
6.1.1 Associations and value types
6.1.2 Bridging from objects to database
In the database, tables represent the entities, and columns represent the value.
6.1.3 Mapping types
entity classes are always mapped to database tables using <class>, <subclass>, and <joined-subclass> mapping elements
6.1.4 Built-in mapping types
.NET Primitive mapping types
Date/Time mapping types
Object Mapping Types
Large Object Mapping Types
Various CLR Mapping Types
6.1.5 Using mapping types
Creating Custom Mapping Types
NHibernate.UserTypes.IUserType.IUserType
Creating an Implementation of IUserType
Creating an Implementation of ICompositeUserType
the order of columns must match the order of properties in your type implementation
An alternative way to represent is to use a component mapping.
The decision to use a custom mapping type is often a matter of taste.
Other Interfaces to Create Custom Mapping Types
NHibernate.UserTypes.IParameterizedType interface allows you to supply parameters to your custom type in the mapping file. SetParameterValues(IDictionary parameters)
NHibernate.UserTypes.IEnhancedUserType interface makes it possible to implement a custom type that can be marshalled to and from its string representation. This functionality allows this type to be used as an identifier or a discriminator type. To create a type that can be used as version, you must implement the IUserVersionType interface.
NHibernate.UserTypes.INullableUserType interface lets you interpret non-null values in a property as null in the database.
NHibernate.UserTypes.IUserCollectionType interface, see the implementation NHibernate.Test.UserCollection.MyListType
Using Nullable Types
NHibernate.NullableDateTimeType from NUllables.NHibernate.dll
using Enumerated Types
IQuery q = session.CreateQuery(“from Comment c where c.Rating = :rating”);
q.SetParameter(“rating”, Rating.Low, NHibernateUtil.Enum(typeof(Rating)));
6.2 Mapping collections of value types
6.2.1 Storing value types in sets, bags, lists, and maps
Using a Set
Using a Bag
BAG - An unordered collection that permits duplicate elements.
Using a List
A <list> mapping requires the addition of an index column to the database table. The index column defines the position of the element in the collection. Thus, NHibernate can preserve the ordering of the collection elements when retrieving the collection from the database if you map the collection as a <list>:
Using a Map
duplicate elements are allowed, unordered
Sorted and Ordered Collections
A sorted collection is sorted in memory using a .NET IComparer.
An ordered collection is ordered at the database level using a SQL query with an order by clause.
sort="natural" - NHibernate to use a SortedMap, sorting the image names according to the CompareTo() method of System.String
other sorted order - specify the name of a class that implements System.Collections.IComparer in the sort attribute.
NHibernate sorted maps use Syste.Collections.SortedList in their implementation.
A Sorted set, which behaves like Iesi.Collections.SortedSet, is mapped in a similar way.
Bags can't be sorted, and there is no SortedBag, unfortunately. Nor my lists be sorted, because the order of list element is defined by the list index.
The expression in the order-by attribute is a fragment of a SQL order by clause. You can even write SQL function calls in the order-by attribute.
You can order by any column of the collection table. Both sets and bags accept the order-by attribute; but lists don't.
NHibernate uses an Iesi.Collections.ListSet and a System.Collections.Specialized.ListDictionary to implement ordered sets and maps; use this functionality carefully because it doesn't perform well with large numbers of elements.
6.2.2 Collections of components
Writing the component class
recommend implement Equals() and GetHashCode() to compare the Name, Filename, SizeX, and SizeY properties, this allows NHibernate dirty checking to function correctly.
better safe than sorry
Mapping the collection
Bidirection navigation
Avoiding not-null columns
idbag offers a surrogate collection key
6.3 Mapping entity associations
association referring to relationships betweent entities.
6.3.1 One-to-one associations
Using a foreign key association
Using a primaray key association
6.3.2 Many-to-many associations
A unidirectional many-to-many association
A bidirectional many-to-many association
inverse="true", tells NHibernate to ignore changes made to the categories collection and use the orther end of the association -the items collection- as the representation that should be synchronized with the database.
<bag> : doesn't involve a surrogate-key column. It lets you use an IList (with bag semantics) in a persistent class instead of an ISet.
a bag doesn't preserve the order of elements.
Indexed collections such as lists and maps can't be used for the inverse end of a many-to-many association, because NHibernate won't initialize or maintain the index column if inverse="true".
an indexed collection, or even arrays, can't be set to inverse="true"
Using a collection of components for a many-to-many association
One-to-many association
The "many" end of this association was implemented in C# with an ISet.
Using a bag with set semantics
recommend using <set> mappings for typical parent/child relationships
Unidirectional mapping
one-to-many association mapping don't need to declare a table name. NHibernate already knows that the column names in the collection mapping belong to the table.
6.4 Mapping polymorphic associations
6.4.1 Polymorphic many-to-one associations
6.4.2 Polymorphic collections
6.4.3 Polymorphic associations and table-per-concrete-class
6.5 Summary
An entity instance has its own lifecycle and persistent identity; an instance of a value type is completely dependant on an owning entity.
A collection doesn’t have its own persistent identity and belongs to a single owing entity.
In practice, we recommend against the overuse of many-to-many associations.
Associations in NHibernate are naturally polymorphic.
------
这个章节应该算是看的比较快的,在项目中使用NHibernate也已经有一段时间了,虽然还有很多不明白的地方,但是多少还是有所体会。看这一章的时候,突然发现第3章和第4章的内容可能需要重读一下。
另外,我在项目中使用了 Unit of Work 的 pattern,遇到了一些问题(多半是因为自己没有学好);不过昨天却看到有人讲,我的那种方式已经“奥特曼”了。之前参考的是一篇2008年的文章,看上去很有道理,更吸引人的是还有单元测试可以帮助理解,但是的确有些年代久远了。
打算周五用一天的时间修复项目里面所使用的 Unit of Work 的 pattern,我现在基本上是每次 Request 之后都会 flush 一下,非常的不环保,而且容易出问题。