2011-11-29 11 views
15

La mia applicazione consente agli utenti di creare ed eliminare oggetti Site. L'ho implementato utilizzando session.add() e session.delete(). Poi ho i pulsanti 'Salva' e 'Ripristina' che chiamano session.commit() e session.rollback().Eliminazione di un oggetto da una sessione SQLAlchemy prima che sia persistuto

Se aggiungo un nuovo Site, quindi lo salvo/lo impegno e quindi lo elimino, tutto va bene. Tuttavia, se provo a rimuovere un oggetto dalla sessione prima che sia stato salvato, viene visualizzato un errore "non persistente".

Codice:

self.newSite = Site('foo') 
self.session.add(self.newSite) 
print self.session.new 
self.session.delete(self.newSite) 

uscita:

IdentitySet([<Site('foo')>]) 

Traceback (most recent call last): 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_comm.py", line 744, in doIt 
    result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec) 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_vars.py", line 375, in evaluateExpression 
    result = eval(compiled, updated_globals, frame.f_locals) 
    File "<string>", line 1, in <module> 
    File "C:\Python27\Lib\site-packages\sqlalchemy\orm\session.py", line 1245, in delete 
    mapperutil.state_str(state)) 
InvalidRequestError: Instance '<Site at 0x1ed5fb0>' is not persisted 

capisco cosa sta succedendo qui, ma non sono sicuro di quello che dovrei fare, invece.

Esiste un altro metodo per rimuovere un oggetto non ancora persistuto da una sessione? O dovrei chiamare lo session.flush() prima di tentare una cancellazione, nel caso in cui l'oggetto che voglio cancellare non sia stato ancora scaricato?

Se si tratta di quest'ultimo, come mai session.query() auto-vampate (garantire che gli oggetti in sospeso visualizzati nei risultati della query), ma non lo fa session.delete() (che garantirebbe che gli oggetti in sospeso possono essere cancellati senza errori).

risposta

13

È possibile Session.expunge() esso. Penso che la logica con lo delete() sia, è preoccupante che tu non tenga traccia delle cose se la mandi in sospeso. Ma posso vedere l'altro lato della storia su questo, ci penserò su. Fondamentalmente lo stato implicito da delete() include alcune supposizioni di persistenza, ma probabilmente non sono così significative come penso. Viene quindi in mente un metodo "expunge or delete", il che è divertente, in pratica è il "save or update" che abbiamo copiato originariamente da Hibernate, che è appena diventato "add". "aggiungi" può fare le transizioni di transitori-> in sospeso e distaccato-> persistente - un potenziale "remove()" esegue sia in sospeso-> transitorio e persistente-> cancellato? troppo male la sessione scopata ha già "remove()" ....

Session.query() autoflushes perché sta per uscire nel database per emettere qualche SQL per ottenere alcune righe; quindi qualsiasi cosa tu abbia localmente bisogno di uscire prima. delete() contrassegna semplicemente lo stato di un oggetto, quindi non è necessario richiamare alcun SQL. Se volessimo che delete() funzionasse in attesa, dovremmo semplicemente cambiare tale asserzione.

È interessante notare che se si utilizza la sessione rollback(), qualsiasi cosa che si è add() all'interno di quella sessione, indipendentemente dal fatto che sia stata svuotata o meno, viene cancellata.

+3

Sono d'accordo con Mike sul fatto che 'delete' potrebbe essere più indulgente. Tuttavia, la situazione attuale è molto semplificata - potrebbero esserci altri oggetti correlati che sono stati esplicitamente o implicitamente (tramite relazioni) aggiunti alla stessa sessione e non commessi. Pertanto, IMO, il modo più pulito è eseguire un 'rollback()' sulla sessione. – van

+0

Grazie, ora ha senso. Quindi, quando si fa clic sul pulsante Elimina, quale dovrebbe essere la logica? Qualcosa come 'try: session.delete (foo); tranne InvalidRequestError: session.expunge (foo) '? Oppure, come da [questa risposta] (http://stackoverflow.com/a/3897845/665488), forse: 'if has_identity (foo): session.delete (foo); else: session.expunge (foo) '? –

+5

Probabilmente direi "se oggetto in session.new: expunge else: delete" – zzzeek

Problemi correlati