On Jan 13, 2011, at 10:18 PM, Russ wrote:

> On Wednesday, January 12, 2011 2:16:00 PM UTC-5, Michael Bayer wrote:
> see expire_on_commit=False as well as Session.commit() for further detail:
> http://www.sqlalchemy.org/docs/orm/session.html#committing
> http://www.sqlalchemy.org/docs/orm/session.html#sqlalchemy.orm.session.Session.commit
> To reassociate detached objects with a session, use Session.add() or 
> Session.merge().  Detachment is described at 
> http://www.sqlalchemy.org/docs/orm/session.html#quickie-intro-to-object-states
>  .
>  
> I think I'm in a catch-22 situation I'm not sure how to get out of (short of 
> copying my object to an unmapped one, which seems wasteful)...
> 
> I have N objects in a scoped session and I want to commit the changes on them 
> all.  After this is done, I want to keep just one of them around in a cache 
> as a simple detached object that won't ever result in emitted SQL.  The 
> business rules are such that for this object there is no way the object will 
> differ from what is in the DB (and even if the DB was changed behind the 
> scenes I want the values at time of commit).
> 
> The issue seems to be that on commit(), everything is expired, and the 
> comment in the docs that says "They are still functional in the detached 
> state if the user has ensured that their state has not been expired before 
> detachment" indicates that I can't have a cleanly detached object after a 
> commit because of this expiration.  At least not without setting 
> expire_on_commit = False... but that applies to all objects in the session.  
> I only want one object to be severed from the database linkage.

So you're looking to do a write-through cache here, i.e. write the DB, then 
write the value straight to the cache.  I think if you were to say 
session.flush(), which emits the SQL, then detach all the objects using 
session.expunge(), they're no longer affected by subsequent session operations, 
then session.commit(), commits the transaction, that would produce the effect 
you're looking for.

> 
> Is there any clean way to set expire_on_commit behaviour at a per-object 
> level?  It seems to be all or nothing at the moment.

Bizarrely, this question had never been asked before, until about five hours 
ago.   That happens quite often, for some reason.   For that user I suggested 
using SessionExtension.after_commit() to re-implement expiration on subsets of 
objects only, though you'd need some plumbing to indicate what objects get the 
expiration - perhaps you'd set some attribute on them.    I think the 
flush()->expunge()->commit() idea is easier.

> 
> I dug into the code that seems to do the expiry (session._remove_snapshot 
> through to InstanceState.expire_attributes) and nothing is leaping out at me. 
>  Can I force an "un-expire" after the commit without legitimately reflecting 
> the persistent state?

Well "un-expire" is just hitting the object's attributes so it loads back 
again, assuming you're looking to not have the extra SELECT.  If you were to 
SELECT all the rows at once in a new query() that also would unexpire all the 
existing objects it hit within the one result set, if that's useful information.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to