2012-12-14 21 views
17

Sono nuovo di SQLAlchemy e ho ereditato un codebase un po 'disordinato senza accesso all'autore originale.Quando dovrei chiamare flush() su SQLAlchemy?

Il codice è scritto con chiamate a DBSession.flush(), apparentemente in qualsiasi momento l'autore desiderava assicurarsi che i dati fossero salvati. All'inizio stavo solo seguendo gli schemi che ho visto in questo codice, ma mentre sto leggendo i documenti, sembra che questo non sia necessario - che l'autoflushing dovrebbe essere installato. Inoltre, sono entrato in alcuni casi con chiamate AJAX che generano l'errore "InvalidRequestError: Session sta già scaricando".

In quali scenari vorrei legittimamente mantenere una chiamata a flush()?

Si tratta di un'applicazione piramide, e SQLAlchemy è in corso di installazione con:

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False)) 
Base = declarative_base() 

risposta

26

La ZopeTransactionExtension sulla DBSession in collaborazione con la pyramid_tm essere attivi sul vostro progetto gestirà tutti i commit per voi. Le situazioni in cui è necessario svuotare sono:

  • Si desidera creare un nuovo oggetto e recuperare la chiave primaria.

    DBSession.add(obj) 
    DBSession.flush() 
    log.info('look, my new object got primary key %d', obj.id) 
    
  • si vuole provare ad eseguire un certo SQL in un punto di salvataggio e il rollback se fallisce senza invalidare l'intera transazione.

    sp = transaction.savepoint() 
    try: 
        foo = Foo() 
        foo.id = 5 
        DBSession.add(foo) 
        DBSession.flush() 
    except IntegrityError: 
        log.error('something already has id 5!!') 
        sp.rollback() 
    

In tutti gli altri casi che coinvolgono l'ORM, la transazione verrà interrotta per voi su eccezioni, o impegnata in caso di successo automaticamente dal pyramid_tm. Se si esegue l'SQL raw, sarà necessario eseguire da solo il transaction.commit() o contrassegnare la sessione tramite zope.sqlalchemy.mark_changed(DBSession) altrimenti non è possibile per ZTE sapere che la sessione è stata modificata.

Inoltre, è necessario lasciare expire_on_commit al valore predefinito di True a meno che non si abbia una buona ragione.

+0

Grazie mille. Follow up: cosa costituisce una buona ragione per avere expire_on_commit = False in questa configurazione? (Non so perché è stato impostato in questo modo in primo luogo). – blocks

+4

Nella mia esperienza, è usato da persone che non sanno quello che stanno facendo e cercano di imbrogliare il sistema usando gli oggetti dopo che sono stati commessi. * ovviamente * dopo un commit, non si ha alcuna garanzia che lo stato di quell'oggetto sia più valido. –

+0

@ Michael Merickel - Molto ben spiegato. Che ne dici di quando non dovremmo usare flush()? [Ci sono effetti collaterali dal chiamare SQLAlchemy flush() nel codice?] (Http://stackoverflow.com/questions/29338419/are-there-any-side-effects-from-calling-sqlalchemy-flush-within-code) –

Problemi correlati