2011-11-29 10 views
15

私のアプリケーションでは、ユーザーがSiteオブジェクトを作成して削除することができます。私はsession.add()session.delete()を使ってこれを実装しました。私はその後、session.commit()session.rollback()を呼び出す "保存"と "リセット"ボタンを持っています。永続化される前のSQLAlchemyセッションからオブジェクトを削除する

新しいSiteを追加して保存/コミットしてから削除すると、すべてが正常になります。しかし、保存する前にセッションからオブジェクトを削除しようとすると、「持続しない」というエラーが表示されます。

コード:

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

出力:

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 

私はここで何が起こっているかを理解し、私は私が代わりにやるべきことはよく分かりません。

セッションから非永続オブジェクトを削除する他の方法がありますか?または、削除したいオブジェクトがまだフラッシュされていない場合は、session.flush()に電話をかけてから削除を試みる必要がありますか?

session.query()が自動でフラッシュされます(照会結果に保留中のオブジェクトが確実に表示されます)。session.delete()は保留中のオブジェクトを確実に削除できます。

答えて

13

Session.expunge()です。私はdelete()という論理的根拠は、それが保留中のものを送信すれば、あなたが物事を追跡していないことを心配していると思います。しかし、私はそれについての話の反対側を見ることができます、私はそれについて考えるでしょう。基本的にdelete()が暗示している状態には、永続性の前提がいくつか含まれていますが、おそらく私が思っているほど重要ではないでしょう。 "expungeまたはdelete"メソッドが頭に浮かびます。これは基本的にHibernateから最初にコピーされた "保存または更新"という面白いものです。これは単に "add"になりました。 "add"は一時的な - >保留中の遷移とdetached-> persistentを行うことができます - 潜在的な "remove()"は保留 - >一時的 - >永続 - >削除されますか?スコープされたセッションはすでに "remove()"を持っています....

Session.query() autoflushes何らかのSQLを出していくつかの行を取得しようとしているので、あなたがローカルで最初に外出する必要があるものは何でも。 delete()はオブジェクトの状態をマークするだけなので、SQLを呼び出す必要はありません。 delete()を保留中に動作させたい場合は、そのアサーションを変更するだけです。

興味深いことに、セッションがrollback()であれば、そのセッション内でadd()が実行されていても、フラッシュされたかどうかに関係なく、消去されます。

+3

マイクには、「削除」がもっと寛容であると私は同意します。しかし、現在の状況ははるかに単純化されています - 明示的または暗黙的に(リレーションを介して)同じセッションに追加されコミットされていない他の関連オブジェクトが存在する可能性があります。したがって、IMO、最もクリーンな方法は、セッションで 'rollback()'を行うことです。 – van

+0

ありがとう、それは今意味があります。だから、削除ボタンをクリックすると、どのようなロジックが必要ですか? 'try:session.delete(foo);のようなものです。 InvalidRequestErrorを除く:session.expunge(foo) '?または、[この回答](http://stackoverflow.com/a/3897845/665488)によると、多分:if has_identity(foo):session.delete(foo); else:session.expunge(foo) '? –

+5

私はおそらく "セッション内のオブジェクトならば、新しい:expunge else:delete" – zzzeek

関連する問題