【问题标题】:When should I be calling flush() on SQLAlchemy?我应该什么时候在 SQLAlchemy 上调用 flush()?
【发布时间】:2012-12-02 23:58:59
【问题描述】:

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

【问题讨论】:

    标签: python sqlalchemy pyramid


    【解决方案1】:

    DBSession 上的 ZopeTransactionExtension 以及在您的项目中处于活动状态的 pyramid_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

    【讨论】:

    • 非常感谢。跟进:在此设置中设置 expire_on_commit=False 的真正充分理由是什么? (我不知道为什么一开始就这样设置)。
    • 根据我的经验,它被那些不知道自己在做什么并试图在提交后使用对象来欺骗系统的人使用。 显然在提交之后,您无法保证该对象的状态不再有效。
    • @Michael Merickel - 解释得很好。什么时候我们不应该使用flush()呢? Are there any side effects from calling SQLAlchemy flush() within code?
    猜你喜欢
    • 1970-01-01
    • 2016-05-02
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多