[odb-users] Problem with object loading view

Boris Kolpackov boris at codesynthesis.com
Tue Mar 8 10:24:23 EST 2016


Hi Marcel,

I finally got to looking into this. Sorry for the delay and thanks for
the test case.

Marcel Nehring <mne at qosmotec.com> writes:

> * I manually load all instances of class Derived from the database.
>   Derived has a polymorphic base class.
> * Loading an instance of Derived triggers loading of a class Foo due to
>   object relationships.
> * Loading of a Foo triggers loading of a Bar, let's call it A.
> * Bars are collected in a BarCollection and they know of the collection
>   they are a member of, so loading a Bar triggers loading of a BarCollection.
> * Loading of a BarCollection triggers loading of all contained Bars,
>   including a Bar B.
> * When Bar B is fully loaded the post load callback fires.
> * Inside this callback I manually try to load a Derived, since loading of
>   the Derived object from the first step is not yet finished it is not
>   present in ODB's session cache.

Just for the record, I think people shouldn't be allowed to do this
king of things ;-).


> (If it were, it would work fine)

Actually, I believe it is another instance being loaded. If it is the same
instance (with the same object id), it will be in the cache (it is entered
first thing, before any statement locking, etc).


> As I said, I am not sure if this is the problem that you already mentioned
> in you last message.

Yes, this is slightly different. You are not loading the view twice
recursively. You are, however, loading the same (type of) object
recursively both via the normal object-loading route and via the
object loading view (OLV). And the OLVs don't expect this. That is,
they except this to be "top-level call" with respect to any object
that they are loading.

I think (theoretically) it is possible to make it work at the expense
of fairly significant extra complexity. Just to summarize, OLV loads
raw data (called object image) for all objects in a single go. So it
uses its custom image type that is essentially an amalgamation of all
the object image types. So in this part it doesn't rely on any
"standard" object loading mechanisms (image, statement, etc.) that
would require locking. However, if the object has containers or
sections, then the view uses the standard mechanisms to load this
part. And that's where locking is required.

Normally, if the lock fails (recursive loading and statements are
already in use), then a "delay load task" is queued and performed
later. This task loads both the object itself and all its containers
and sections. As a result, we cannot just reuse this task (we have
already loaded the object itself) and will have to come up with a
special one that will only load the containers/sections. This will
add quite a bit of hair, especially in the polymorphic case and I
am not very keen on going this route.

One fairly simple workaround, for your case at least, would be to
use a lazy pointer for the Foo relationship. The idea is to first
load all the derived objects (so they all end up in the session).
Then have another loop that loads all the relationships. What do
you think?

Boris



More information about the odb-users mailing list