Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
When Flushing Goes Bad: Assigned IDs in NHibernate

I have an aggregate root that creates another persistent entity and places it in a collection.

Typically, I try to avoid letting the internal id used within an aggregate boundary seep outside, but for the purpose of mapping the relevant instance to the ui data being sent, I needed to get the id and pass it back to the ui.

Using this mapping on the newly created entity:

<class name="AggregateRoot" table="RootsButNotTheBook">
    <!--snip-->
    <set name="ChildEntities" class="ChildEntity" cascade="all"> <!--more-->
</class>
<class name="ChildEntity" table="ChildEntities">
        <id name="Id" type="Guid" >
            <generator class="assigned"/>
        </id>
        
    <!--more mapping-->

 

and trying this code:

aggregateRoot.CreateChildEntityAndAddToCollection();
session.Update(aggregateRoot);
session.Flush();

Will get me this NHibernate exception:

NHibernate.StaleStateException: Unexpected row count: 0; expected: 1

Why? Well, inside my ChildEntity creation logic, I am generating an id for the entity so NHibernate thinks that it is a previously persisted entity ... but of course it isn't.

To make this work I change my child entity mapping to :

<class name="ChildEntity" table="ChildEntities">
        <id name="Id" type="Guid" >
            <generator class="assigned"/>
        </id>
        <version name="LastModifiedOn" 
                type="timestamp" 
                column="LastModifiedOn" 
                access="nosetter.camelcase" />
    <!--more mapping-->

Adding the Versioning element to my entity now lets NHibernate know how to deal with the entity as it should and the code now works swimmingly.

The Hibernate documentation states:

A version or timestamp property should never be null for a detached instance, so Hibernate will detact any instance with a null version or timestamp as transient, no matter what other unsaved-value strategies are specified. Declaring a nullable version or timestamp property is an easy way to avoid any problems with transitive reattachment in Hibernate, especially useful for people using assigned identifiers or composite keys!

Therefore I actually used a nullable DateTime on my ChildEntity class, but things seemed to work even when I used a non-nullable DateTime, so I am not sure what I am missing there. Let me know if there are any errors in anything I present here...


Posted 07-29-2008 7:24 PM by Michael Nichols

[Advertisement]

Comments

Ken Egozi wrote re: When Flushing Goes Bad: Assigned IDs in NHibernate
on 07-30-2008 3:34 AM

Personally I try to avoid assigned for surrogate keys, Guid being as surrogate as it gets.

Instead, I go for the builtin GuidComb implementation in NH.

that way, NH will know to use the unsaved-value to figure out it needs to INSERT.

Mike wrote re: When Flushing Goes Bad: Assigned IDs in NHibernate
on 07-30-2008 11:27 AM

@Ken

I needed to have access to the id prior to the flush, so I was kind of forced into an assigned strategy since the id would not be generated by NH until then.

I would prefer using a business key and circumvent this whole issue but it just didn't make sense in this case.

Christopher Steen wrote Link Listing - July 30, 2008
on 07-31-2008 2:08 AM

Link Listing - July 30, 2008

So you want to learn NHibernate? - Part 1 of 1, The Links « HSI Developer Blog wrote So you want to learn NHibernate? - Part 1 of 1, The Links &laquo; HSI Developer Blog
on 07-31-2008 6:27 PM

Pingback from  So you want to learn NHibernate? - Part 1 of 1, The Links &laquo; HSI Developer Blog

Frederik Gheysels wrote re: When Flushing Goes Bad: Assigned IDs in NHibernate
on 08-04-2008 6:47 AM

This is strange indeed ...  But, maybe the NH docs is not really up-to-date for this issue.

(IMHO, it is also not up to date for some other stuff as well, like the default value for the lazy attribute, or the default fetch strategy).

Anyway, how was this done before .NET supported nullable types ? Perhaps NHibernate looks at the default value of a value type as well to determine wether the object should be treated as transient or not ?

Anyway, you could also make use of the 'IsUnsaved' method of an interceptor to determine whether an object is transient or not.

So you want to learn NHibernate? (or, NHibernate Hyperlink Acupuncture) | The Freak Parade wrote So you want to learn NHibernate? (or, NHibernate Hyperlink Acupuncture) | The Freak Parade
on 08-08-2008 3:29 PM

Pingback from  So you want to learn NHibernate? (or, NHibernate Hyperlink Acupuncture) | The Freak Parade

Hugo Ribeiro wrote NHibernate and Row Versions (Insert/Update Records)...
on 10-09-2008 12:10 PM

I don't like NHibernate! As I use it more and more, I come to terms with this fact and with the fact

MIke wrote re: When Flushing Goes Bad: Assigned IDs in NHibernate
on 10-09-2008 1:22 PM

@Hugo

I love working with NHibernate and disagree strongly with your findings in your post. While I concede it takes work to grasp the concepts it employs, I think it is worth it in the end.

Sam wrote re: When Flushing Goes Bad: Assigned IDs in NHibernate
on 08-24-2009 8:18 AM

Hey Mike

Could you perhaps supply a code download for the examples above. My probs seems to be with the mapping files and would appreciated complete hbm files.

Thanks for the post

S

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)