Null Collection Upon Lazy Invocation

110 views
Skip to first unread message

Tim Scott

unread,
Apr 5, 2012, 5:29:25 PM4/5/12
to nhusers
After upgrading to NH 3.2.0.4000 we now get an exception here because
orderDates is null.

foreach (var orderDate in orderDates)

It's declared thusly:

protected IList<OrderDate> orderDates = new List<OrderDate>();

And mapped like this:

<bag name="orderDates" access="field.camelcase" inverse="true"
lazy="true" cascade="all-delete-orphan" >
<key column="OrderId" />
<one-to-many class="OrderDate" />
</bag>

A few frames down in the stack trace is:

at NHibernate.Proxy.DefaultLazyInitializer.Intercept(InvocationInfo
info)

There are no matching order date rows in the database.

Why is NH lazy initializing this collection to null instead of
empty? How can I fix?

Fabio Maulo

unread,
Apr 7, 2012, 5:26:57 PM4/7/12
to nhu...@googlegroups.com
Is not a matter of initialization but a matter of access.
probably you are trying to access to the field from a no virtual property and the instance you are using is a proxy.

Tim Scott

unread,
Apr 11, 2012, 5:00:12 PM4/11/12
to nhusers
The protected field that is null (orderDates) is accessed via a public
virtual property getter. This property is read-only (no setter). The
field (orderDates) is not referenced directly in this property getter
but a few private methods down.

Incidentally, the error appears only after the same code path is
called many times (in a loop) without error. The error appears on a
particular instance of an entity (Order).

I feel certain that the entity (Order) has all of it's public members
as virtual (it's proxy-able) because it is mapped as lazy=true.

Tim Scott

unread,
Apr 13, 2012, 10:25:55 AM4/13/12
to nhusers
When I replace my reference to mapped orderDates field with a
reference to public virtual property OrderDates (which simply
orderDates), the problem goes away.

So this fails:

1) call public virtual property ActualDeliveredDate getter
2) calls a few levels down into private methods
3) last private method references mapped private field orderDates
4) orderDates is null

While this succeeds:

1) call public virtual property ActualDeliveredDate getter
2) calls a few levels down into private methods
3) last private method references public virtual property OrderDates
4) OrderDates references orderDates, which is not null

So the difference is nothing to do with the public surface of the
entity but what some private method calls. It's really painful to
think that we must take care throughout a class to not access it's own
private data directly from other private members. I would call that a
bug.

But in working through this, I hit upon another place where I
apparently do not understand NH 3 behavior. The error only occurs
when the Order is actually an OrderProxy. The client code looks
something like this.

dto.Foo = parent.Order.Foo;
dto.Bar = parent.Order.Bar;
dto.ActualDeliveryDate = parent.Order.ActualDeliveryDate;

When this code is entered, Order is still a proxy because it is mapped
as lazy="proxy". But should not the proxy be invoked on the first
line? By the time the third line is hit shouldn't it be a real
Order? What does trigger invocation of lazy many-to-one properties?
Reply all
Reply to author
Forward
0 new messages