Dňa pondelok, 18. februára 2013 18:54:22 UTC+1 Michael Bayer napísal(-a): > > > > On Feb 18, 2013, at 12:10 PM, Juraj Variny <[email protected] <javascript:>> > wrote: > > Hello, > > I should have expected refresh() to have problem with dirty objects, but > if it isn't a bug, maybe it should be at least documented. > > To explain whole situation and why do I call the refresh() at all: I have > Account persistent class, with balance property. When doing processing, I'm > locking the row whenever it is necessary to update it (to not lock more > rows than necessary), like: > > def update(acct,...): > DBSession.refresh(acct,lockmode='update') > #update balance, add transaction record,return > > The problem is, this function can be called multiple times in one session > and subsequent refresh calls throw out unsaved changes. So far I have fixed > it by placing DBSession.flush() calls. But calling flush() in the middle of > processing implies risk of problems with unmatched constraints (not fully > fleshed out data). Another idea is to mark already locked objects so that > refresh() is called only first time in a transaction. Such reentrant > behavior may be useful to have, what do you think? > > > if you just want to emit a SELECT .. FOR UPDATE you can just emit that > directly. If you specify with_lockmode() on query(), the get() will emit > a SELECT unconditionally: > > session.query(Account).with_lockmode('update').get(my_account.id) > > it would be more efficient to not emit this SELECT more times than needed > though this is easy enough to roll on top of a session, like a > "lock_object()" function...can be tracked with events, here's also > generalized: > > from sqlalchemy import event > from sqlalchemy.orm import Session, object_session, object_mapper > > @event.listens_for(Session, "after_begin") > def setup_lock_collection(session, *args): > session._locked = set() > > @event.listens_for(Session, "after_commit") > @event.listens_for(Session, "after_rollback") > def clear_lock_collection(session): > session._locked.clear() > > def lock_object(obj): > session = object_session(obj) > mapper = object_mapper(my_account) > pk = mapper.primary_key_from_instance(my_account) > if (mapper, pk) not in session._locked: > session.query(mapper).with_lockmode('update').get(pk) > session._locked.add((mapper, pk)) > > Nice, looks exactly like what I need! I guess my_account should be changed into obj ?
-- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/sqlalchemy?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
