On Aug 1, 2011, at 6:25 AM, Torsten Landschoff wrote:
> Hello world,
>
> I am tearing my hair about my SQLAlchemy usage in a GUI application,
> especially to get it error tolerant.
>
> Usually the GUI filters user inputs before they are thrown at SQLAlchemy
> to store it into the database. If that fails, however, it can happen
> that data is thrown at the database that leads to a rollback because of
> e.g. violated foreign key constraints.
>
> If that happens, the session rolls back (fine) but the GUI still shows
> the state that I tried to write into the database. Being MVC, I would
> need all database object to fire a "changed" event so they are pulled
> fresh from the database.
The Session's default behavior is to expire fully the state present after a
rollback occurs. The next access of any attribute will guaranteed pull fresh
from the DB in a new transaction.
I'm assuming you know this, and that there is something additional here you're
looking for, like an event to the GUI to actually re-access the attributes, or
something.
>
> I tried using the after_commit extension (SQLAlchemy 0.6.8) to do this.
> Paraphrased, this works like this:
>
> def after_rollback(self, session):
> for instance in session:
> instance.signal_changed()
>
> This works fine if the transaction being rolled back is the toplevel
> transaction. However, if that is a nested transaction, this destroys my
> session state (as the listeners try to load from the database):
>
> InvalidRequestError: This Session's transaction has been rolled back by
> a nested rollback() call. To begin a new transaction, issue
> Session.rollback() first.
A surprise for me. Yes the after_rollback() seems to only fire after an
actual database rollback. This is a bug in that there is no way to catch soft
rollbacks. I can't change the event, as it is integral in transactional
extensions like that supplied for Zope; a new one will have to be added and the
docs for after_rollback() will need to be updated.
Ticket #2241 is added for this and is completed. You can now use the 0.7 tip
and use the after_soft_rollback() event in conjunction with the is_active flag:
@event.listens_for(Session, "after_soft_rollback")
def do_something(session, previous_transaction):
if session.is_active:
session.execute("select * from some_table")
http://www.sqlalchemy.org/trac/ticket/2241
http://hg.sqlalchemy.org/sqlalchemy/rev/94d54a7e4d49
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.