views:

134

answers:

1

I started switching some pre-existing nHibernate code in a Sharepoint-based ASP.NET project from eager loading and a new session every database hit, to lazy loading and a session for the duration of the HTTP request, and started running into a problem.

When we create an Item in this system, there are some many-to-one relationships that are populated by dropdowns. That gets us the ID, which is enough to save to the database.

In order to perform some post-save tasks like email notification, we then load that same item back, which previously would get us the entire object tree populated.

However, since the change to lazy loading and a session with the lifetime of the entire request, we've been getting NullReferenceExceptions from properties below Item that are mysteriously null.

We load the item through nHibernate into changedItem. The call that's failing is:

changedItem.PaperMedia.FormsAnalyst.User.Contact.Name

PaperMedia is fully populated, but everything on FormsAnalyst is null except the ID.

This is the same state as when we saved it, so one possible cause of this problem is the Item being cached and simply retrieved, nHibernate thus being ignorant of the actual values from the database. However, I'm committing the transaction, plus explicitly calling Flush() on the session, between the save and the subsequent load, so if that's the case, neither Commit() nor Flush() is not having any effect on the cache.

I have changed these properties in the relevant hbm.xml files to be lazy="false", and have SetFetchMode FetchMode.Eager for all of them as well, to no effect.

I was also considering max_fetch_depth as the issue. If I call Refresh(changedItem) on the session, it has no effect. However, if I call Refresh(changedItem.PaperMedia), it will populate all the way down to Name. This would seem to discount max_fetch_depth as the problem, but I've nonetheless made an attempt to increase it, setting it to 6 in the hibernate.cfg.xml as well as SetProperty("max_fetch_depth", "6") on the configuration instance while creating the session factory, and these have had no effect either.

I don't know what else to try.

Anyone seen anything like that before? I'm new to nHibernate so it might be something simple...

Edit:

It would seem that caching is indeed the issue. Calling Clear() on the session instance fixes this behavior.

So the question now becomes, why would Flush() not update the cached items? That's exactly what I thought it was built to do.

A: 

I think that Flush() is only for sending changes to the database... it would update the cache with the referenced objects if they were in memory at this time. So, you could either use another session or Clear()... or populate FormsAnalyst in the first place.

fwalch
well, populating the children in the first place isn't a great option, since it's a new item the user is creating so I'd have to send all that extra data to the client and have them send it back. Clear() was working well in that scenario, but causing problems with future lazy-loading with that session after Clear() was called. I've resorted to the hacky Refresh(changedItem.PaperMedia) for now, but am still puzzled. If Flush() is only for sending changes to the database, will it never get changes back?
Grank