Mapping NHibernate collections one way

I encountered an issue with an NHibernate mapping today that took me a short while to solve so I thought I’d post here to remind myself in future.

I wanted to map a parent child relationship but only manage the persistence from the parent end. Here’s an example:

Blog -< Post

  public class Blog
  {
        public Blog()
        {
        }

        public virtual int BlogId { get; set; }

        public virtual IList<Post> Posts { get; set; }
   }

Which might have the following mappings:


The problem I was having was that saving the blog entity was causing a SQL exception complaining that BlogId wasn’t a nullable field on the Post table. In the end the fix was easy – remove the not null constraint!

The reason being that nhibernate likes to save the Post records first, then go back and update the foreign key values once it has saved the Blog entity.

NHibernate onFlushDirty has null previousState

The problem

We use an Entity interceptor to create audit records when we update most tables. We also do a lot of our data access through .NET remoting. This means that we open a session to load the object, the object is detached, serialized, modified, then reattached to the session when we want to persist the changes.

We noticed that in the cases where we are updating detached objects, although the update was being applied correctly there were no audit records appearing in the database. On investigation we realised that the previousState parameter passed into the onFlushDirty method of our interceptor was null.

Why

In the Save method of our data access class we were using the SaveOrUpdate method of the NHibernate session to persist the changes. Section 10.7 of the documentation states:

saveOrUpdate() does the following:

  • if the object is already persistent in this session, do nothing
  • if another object associated with the session has the same identifier, throw
    an exception
  • if the object has no identifier property, save() it
  • if the object’s identifier has the value assigned to a newly instantiated
    object, save() it
  • if the object is versioned (by a or ), and
    the version property value is the same value assigned to a newly instantiated
    object, save() it otherwise update() the object

and merge() is very different:

  • if there is a persistent instance with the same identifier currently
    associated with the session, copy the state of the given object onto the
    persistent instance
  • if there is no persistent instance currently associated with the session,
    try to load it from the database, or create a new persistent instance
  • the persistent instance is returned
  • the given instance does not become associated with the session, it remains
    detached

As our detached objects had an Id and version when we called SaveOrUpdate() they were being updated, and seeing as all update() does is reattach an object to the session, the session had no record of the changes that had been made to that object since it was loaded.

The solution

The solution was to use the merge() method (new in NHibernate 2.0). Merge() checks the first level cache to see if an object with the given identifier has previously been loaded. If so it loads that object out of the first level cache and updates it’s properties using the detached object. This means that the session is now able to track the changes made to the object so that when the flush occurs the previousState is no longer null.

NHibernate 2.0 and the join table syntax

I’ve noticed my post on Mapping a view with NHibernate is always quite popular. Resorting to mapping from a view has worked fine in the past as long as you only required read access, but if you wanted to build a complex object relational mapping that you could update you were in trouble…

Until Now

With NHibernate 2.0 recently being released we now have access to the join table syntax in our mapping documents. This means we can now build more sophisticated domain objects that map on to more than one table. NHibernate takes care of the multi-table inserts and updates behind the scenes making your life easier.

This has to be one of the most underrated features of NHibernate 2.0 as it finally allows you to break away from the one to one mapping between domain objects and your relational model which has ultimately caused compromises in the past.

I urge you to check out this and the other fantastic new features available in the latest NHibernate release.

Mapping view with Nhibernate

Something we’ve come up against in the last week is a need to map a view in Nhibernate. We have a reasonably complex data model with a hierarchical structure involving about four different tables that we wanted to represent as a single mapped entity in our object model. The obvious approach was to define the appropriate view and map that.

No joined tables in Nhibernate:

There seems to be some confusion on the web with a lot of people complaining that Nhibernate doesn’t yet support the joined tables syntax that is available in Hibernate 3.0. While this is true, it doesn’t prevent you from working with a database view as long as you don’t need to update the underlying tables via Nhibernate.

The solution:

Map the view just as you would map any other table in your data model with the standard syntax:

<class name=”MyEntity” table=”MyView”/>

The only other change you need to make is in your property mapping. Add the update and insert attributes to ensure Nhibernate doesn’t try and generate insert and update statements for your view.

<property name=”MyProperty” type=”String” column name=”MyColumn” length=”300″ sql-type=”varchar” not-null=”true”update=”false” insert=”false”/>

That is probably obvious to most people, but there seemed to be enough confusion when I was searching about it that it seems worth stating it again here.