19

私は SQLAlchemy を初めて使用し、元の作成者にアクセスせずにやや乱雑なコードベースを継承しました。

DBSession.flush()作成者がデータが保存されていることを確認したいときはいつでも、コードは への呼び出しで書かれています。最初は、このコードで見たパターンに従っていただけでしたが、ドキュメントを読んでいると、これは不要なようです。自動フラッシュを配置する必要があります。さらに、「InvalidRequestError: Session is already flushing」というエラーを生成する AJAX 呼び出しでいくつかのケースに遭遇しました。

合法的に flush() の呼び出しを維持したいのは、どのようなシナリオですか?

これは Pyramid アプリであり、SQLAlchemy は次のようにセットアップされています。

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

1 に答える 1

30

プロジェクトでアクティブになっていることと連動して、ZopeTransactionExtensionすべてのコミットが処理されます。フラッシュが必要な状況は次のとおりです。DBSessionpyramid_tm

  • 新しいオブジェクトを作成し、主キーを取得したいとします。

    DBSession.add(obj)
    DBSession.flush()
    log.info('look, my new object got primary key %d', obj.id)
    
  • トランザクション全体を無効にすることなく、失敗した場合にセーブポイントとロールバックでいくつかの SQL を実行しようとします。

    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()
    

ORM が関係する他のすべてのケースでは、例外が発生するとトランザクションが中止されるか、成功すると によって自動的にコミットされpyramid_tmます。生の SQL を実行する場合は、transaction.commit()自分で実行するか、セッションをダーティとしてマークする必要があります。zope.sqlalchemy.mark_changed(DBSession)そうしないと、ZTE がセッションが変更されたことを知る方法がありません。

また、よほどの理由がない限りexpire_on_commit、デフォルトのままにしておく必要があります。True

于 2012-12-15T04:39:02.663 に答える