I'm working on some code that is doing some moderately heavy data processing with NHibernate (yes, I know, perhaps not really the right tool for the job. But it's what I've got to work with)
I use a stateless session to get the first 1000 objects, check, update and add them to a list of updated objects if needed. I then repeat for the next 1000 objects until I'm done. Below is a significantly simplified version of the code.
List<MarketOrder> updated = new List<MarketOrder>();
IStatelessSession session = SessionProvider();
int offset = 0;
bool moreToGet = true;
while (moreToGet)
{
var result = session.Query<MarketOrder>().Where(o => o.Owner.ID == currentEntityID && !o.Updated);
var tmp = result.Skip(offset).Take(1000);
foreach (MarketOrder item in data)
{
notUpdated.OrderState = MarketOrderState.Closed;
updated.Add(notUpdated);
}
if (data.Count == pageSize) { offset += pageSize; }
else { moreToGet = false; }
}
Another stateless session is then opened to do a bulk update
IStatelessSession session = SessionProvider();
foreach (MarketOrder o in updated) { session.Update(o); }
When I run my unit test, I get an error:
Test 'TestProcess_AutoCloseOrder' failed: NHibernate.PropertyValueException : Error dehydrating property value for Data.Models.MarketOrder.Owner
---- NHibernate.PropertyAccessException : Exception occurred getter of Common.Models.ModelBase.Version
-------- System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
------------ NHibernate.SessionException : proxies cannot be fetched by a stateless session
After some messing around, I figured that the error is because, in the Update, NHibernate is trying to access the Owner
property of the MarketOrder
being saved. (I assume this is to cascade the update)
Owner
is populated with a proxy and since it was loaded from a stateless session, cannot be accessed.
Sure enough, if I load from a regular session instead of a stateless session it all works fine. This solution will result in a performance hit in production though so I'd rather avoid it.
I could set Owner
to not lazy load but that is not a practical solution for all similar cases.
The answer to this question: NHibernate: proxies cannot be fetched by a stateless session error message. Suggests fetching the problem property as part of the initial load but that seems very wasteful. I only want to update a few properties on the main object, why should I have to load all that object's child references as well?
What I want is for NHibernate to realise that only the main MarketOrder
object has changed and not bother to cascade the update to Owner
. In fact, now I think about it, I didn't think Stateless Session was supposed to cascade updates at all?
So anyone know what's going on here and how I can resolve it?