19

我是 SQLAlchemy 的新手,并且在没有访问原作者的情况下继承了一个有点混乱的代码库。

代码中包含对 的调用DBSession.flush(),似乎在作者想要确保数据被保存的任何时候。起初我只是按照我在这段代码中看到的模式,但是当我阅读文档时,似乎这是不必要的——自动刷新应该到位。此外,我遇到了一些 AJAX 调用的情况,这些调用会生成错误“InvalidRequestError: Session is already flushing”。

在什么情况下我会合法地继续调用flush()?

这是一个 Pyramid 应用程序,正在设置 SQLAlchemy:

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

1 回答 1

30

ZopeTransactionExtension与在您的项目中处于活动状态DBSession相结合的onpyramid_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)否则中兴通讯无法知道会话已更改。

此外,除非您有充分的理由,否则您应该expire_on_commit默认离开。True

于 2012-12-15T04:39:02.663 回答