Tuesday, 13 October 2009

NHibernate – When ‘Load’ does ‘Load and Update’

I came across a truly bizarre update occurring within my Gemini Mailbox Processer Application. It was reported to me by a friend who did some monitoring on the application. We were both completely baffled why NHibernate would be doing any form of update on a simple List<IEmail> call. Let’s look at the details.

Firstly, let’s see the interface which defines the class. I have removed some fields for brevity.


Then here is our code which will load the Emails. Here we create our criteria object, and add some filtering, some ordering, and then retrieve a list of IEmail objects. Nothing seems strange here.


This is the mapping (abbreviated version) to the email class. You might spot the issue in here (but I’ll spell it out later)


Ok, so running this, let’s use NHibernate Profiler to see what is going on.


As you can see, there is a bizarre update statement. At least NHibernate was batching it up into one statement, but WHY! Let’s look at the specific details for this query. Again some items have been removed to keep the snippet small.


I decided to comment out lines in the mapping and run a test app to see what results were returned. Each time I ran it until I saw this update appear. Trial an error narrowed it down to the Priority column.

We can see the priority is looking a little strange. In the interface it is an enum, and in the mapping it is specified as an Int32. So it seems strange that NHibernate it sending it as Text? Let’s remove the Type=”Int32” from the mapping and see what happens.


Rerunning it shows it is all ok now. So while I do not know why, I do now know how to prevent it. I assume it is to do with the type conflict between the enum and specifying it as an Int32.



  1. The issue is probably one of mismatched types.
    When NH commits a transaction, it checks if stuff have changed.
    When you have different types (int32 for NH, enum for the model), that is always going to return a changed entity.

  2. Thanks for clearing that up for us. Does this mean that we don't need to call saveorupdate(), merely make the change within a transaction? Presumably it is better to write clear code as to what is happening?