NHibernate from the ground up – Part 3: Collection Mapping

Download NHibernate 3.zip (1689.0K)

In this part of the NHibernate from the ground up series, we will work through collection mapping by adding Comments to our Post object.

Before we do however, there are a couple things to note.

  1. I created a new solution based on Part 2 and reorganized it a bit. In particular the ViewModels were moved into their own folder, leaving the domain models solely in the Models folder. I also suffixed “Entity” to the domain models so instead of Post we have PostEntity.
  2. I added a Schema Controller that will update the schema based on the mapping. More on this in a second. I want to be very clear however, that I would NEVER PUT THIS IN PRODUCTION CODE! It is destructive, meaning that it drops and recreates the schema every time it is run. This is great in a development environment and should ideally be placed in a separate project that will not get deployed to a production server.

Schema Generation

Schema generation is quite simple with NHibernate. You an use it instead of manually creating tables for your objects to get mapped to. NHibernate will generate the schema based on the mapping. In fact, most of the mapping properties are related directly to the schema generation. Add the following to the global.asax file.


The first thing we need to do is create a new SchemaExport object passing the current configuration to its constructor.

Then we tell NHibernate to first Drop, then Create the schema.

That’s pretty much it to update schema, to use it just call this method, in this case I created a SchemaController with an Update action.


Adding Comments to the PostEntity

Now lets add some Comments to our PostEntity. Create a new CommentEntity in the Models folder.


Its a pretty basic entity and notice that we add a PostEntity so we always have a reference back to its parent.

Now we can update the PostEntity so that it has a collection of Comments.

First we need a place to store the comments so add a private ISet<CommentEntity> field to the PostEntity.


What is a set?

A set is a collection type in the Iesi.Collections library. NHibernate understands two (really three, but one is just an indexed list) types of collections; sets and bags. A set is a collection type that does not allow duplicate objects and is implemented through the ISet interface in the Iesi.Collections assembly. A bag on the other hand allows duplication and is implemented trough a standard IList. Which one do you use? Its up to you, need to have duplicate objects in the collection, use a Bag, don’t want duplicate objects use a Set.

It should be noted that since the Set does not allow duplicates, it becomes important to override the Equals and GetHashCode methods to properly identify a duplicate object.

Now we need to add to the comments collection.

Do this by adding an AddComment method on the PostEntity.


You can see we take in a name and the text of the comment. Then using that data, create a new comment and finally adding it to our internal collection. We have completely encapsulated the adding of comments. This means that there is one and only one way to add a comment to a post. So if we needed to put additional logic around the behavior of adding a comment, there is only one spot to do it in.

Getting the Comments can be done with a read only property.


Notice the use of the ReadOnlyCollection, I could use an IEnumerable<CommentEntity> but I prefer the ReadOnlyCollection as I can using indexing and Count without resorting to Linq.

Now with the objects created, we can map them.

Mapping the Comment

Just like the mapping for the Post, create a new xml file named CommentEntity.hbm.xml and set the build action to “Embedded Resource”


Much like the PostEntity created earlier with the addition of the many-to-one node. This simply tells NHibernate that the foreign key for the Post object is PostId and that this is the “many” side of a one to many relationship.

Updating the Mapping for the Post

With that done can update the mapping for the Post, so that NHibernate knows that a Post has many Comments.


All we did was add the set node to the mapping. Just like in all other mapping nodes, we must supply a name. We also tell NHibernate, by the access attribute, that when it looks for this relationship to look for a field named the same thing as the name, camel cased.

The inverse attribute is telling NHibernate that the “other” side of this relationship should be used for persisting the Comment. The only time where you would like set this attribute to false is when the child object has no knowledge of its parent. Which would in essence make the association unidirectional instead of bidirectional.

The cascade attribute tells NHibernate that when this object is saved, it should cascade those changes down to the comments and if this post is ever deleted, it should delete all the comments that would be orphaned.

The key node with the column attribute ties the foreign key relation up.

The one-to-many node lets NHibernate know the type of the child class and finally the not-found attribute lets NHibernate know what to do if there is an invalid foreign key.

Generating the Schema

With the mappings in place we can generate the schema which gives us the following.



That’s pretty much is for this post. We created a new CommentEntity and mapped it. Updated the PostEntity mapping so we now have a bidirection relationship between Post and Comments. And we setup SchemaGeneration so we don’t have to manually create our tables.

What’s Next?

The next post in the series should be a bit shorter and we will go over many to many mapping by adding Tags to our Post.


TrackBack URL for this entry:

Listed below are links to weblogs that reference NHibernate from the ground up – Part 3: Collection Mapping:


You can follow this conversation by subscribing to the comment feed for this post.

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.


Post a comment