Detached instances and lazy-loaded attributes

690 views
Skip to first unread message

YKdvd

unread,
Jan 24, 2013, 1:54:14 PM1/24/13
to sqlal...@googlegroups.com
If I have an instance "MyInstance" with an attribute "itsLazyAttribute" from a relationship, where everything is defined and queried with lazy loading, then the attribute is lazily loaded, and only filled in when I access it (perhaps, x=len(MyInstance.itsLazyAttribute).   But if not accessed before the instance is detached (session closed, or expunge called) then the attribute will be unavailable, and trigger a DetachedInstanceError (not bound, lazy load operation cannot proceed).

All fine, but is there any way to automatically trip all the lazy triggers before detaching an instance?  Something like a "session.fullyLoad(MyInstance)" type of call?  I couldn't seem to see anything that would do this.  I can redo things to do an eager query, but I was wondering if I was missing something?

Michael Bayer

unread,
Jan 24, 2013, 2:20:05 PM1/24/13
to sqlal...@googlegroups.com

On Jan 24, 2013, at 1:54 PM, YKdvd wrote:

> If I have an instance "MyInstance" with an attribute "itsLazyAttribute" from a relationship, where everything is defined and queried with lazy loading, then the attribute is lazily loaded, and only filled in when I access it (perhaps, x=len(MyInstance.itsLazyAttribute). But if not accessed before the instance is detached (session closed, or expunge called) then the attribute will be unavailable, and trigger a DetachedInstanceError (not bound, lazy load operation cannot proceed).
>
> All fine, but is there any way to automatically trip all the lazy triggers before detaching an instance? Something like a "session.fullyLoad(MyInstance)" type of call? I couldn't seem to see anything that would do this. I can redo things to do an eager query, but I was wondering if I was missing something?

scalar, column-bound attributes will all load at once if you touch one of them. But a relationship()-bound attribute is always an independent entity, for the reason that loading these relationships requires a whole SQL query for the one attribute as it is.

the strategies for this kind of thing usually go in this order:

1. don't try to use detached objects. Philosophically, an object allows "detachment" only so that it can be stowed away somewhere temporarily, or moved between two Sessions. There's not a lot of use cases IMO that really require detached objects to be usable. In my view it's kind of like the object is "asleep".

2. try to load the object as fully as you need at load time, using eager loading. this can save on having to do lots of individual SELECT statements if you're lazy loading.

3. to actually lazy load everything you'd need to employ some technique, in 0.8 this is easy:

from sqlalchemy import inspect

insp = inspect(myobject)
for key in insp.relationships.keys():
getattr(myobject, key)

if in 0.7 you'd need to iterate like this:

from sqlalchemy.orm import object_mapper
from sqlalchemy.orm.properties import RelationshipProperty

mapper = object_mapper(myobject)
for rel in mapper.iterate_properties():
if isinstance(rel, RelationshipProperty):
getattr(myobject, rel.key)


YKdvd

unread,
Jan 24, 2013, 3:23:48 PM1/24/13
to sqlal...@googlegroups.com
I was going to look at some sort of "walk and trigger" but SQLA is elegant enough that I suspected I was either missing a function that already did this, or was fighting against the design philosophy.  Sounds like the latter... :)

My background gives "detached" a less ephemeral flavour, especially in a long-persisting rather than web app - this was sort of "configuration" stuff that was loaded and read-only referenced.  I'm sort of recreating a legacy system and designing on the fly, and hadn't quite resolved whether the loading session was going to remain open, and the bit that loaded the stuff didn't have a lazy/eager option.  I'll have no problem in this case to rejigger to eager-load at query time, or even make the relationships eager.  Thanks for the feedback.
Reply all
Reply to author
Forward
0 new messages