SQLAlchemy会话:如何让它保持活力?

时间:2012-10-04 11:05:39

标签: session transactions sqlalchemy python-3.2

我有一个会话对象被传递了很多,并且在某些时候调用了以下代码行(这是不可避免的):

import transaction
transaction.commit()

这会使会话无法使用(我认为通过关闭它)。

我的问题是两部分:

  1. 如何查看会话是否还活着?
  2. 是否有一种快速恢复死亡会话的方法?
  3. For 2:我目前知道的唯一方法是使用sqlalchemy.orm.scoped_session,然后多次调用query(...)get(id)来重新创建必要的模型实例,但这似乎非常低效。

    修改

    以下是导致错误的事件序列示例:

    modelInstance = DBSession.query(ModelClass).first()
    import transaction
    transaction.commit()
    modelInstance.some_relationship
    

    这是错误:

    sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <CategoryNode at 0x7fdc4c4b3110> is not bound to a Session; lazy load operation of attribute 'children' cannot proceed
    

    我真的不想关闭延迟加载。

    修改

    在这种情况下,DBSession.is_active似乎没有迹象表明会话是否确实存在并且很好:

    transaction.commit()
    print(DBSession.is_active)
    

    这会打印出真......

    修改 这对评论来说似乎太大了,所以我把它放在这里。

    zzzeek说: “只要您访问过任何内容,过期的对象就会通过会话自动从数据库加载新状态,因此无需告知会话在此处执行任何操作。”

    那么我如何以这样的方式获得承诺呢?调用transaction.commit是错误的,这是正确的方法吗?

1 个答案:

答案 0 :(得分:1)

所以首先要注意的是“导入事务”是一个名为zope.transaction的包。这是一个通用事务,它通过zope.sqlalchemy扩展来保存任意数量的子任务,其中SQLAlchemy Session就是其中之一。

zope.sqlalchemy这里要做的是调用Session本身的begin()/ rollback()/ commit()方法,以响应它自己对“事务”的管理。

Session本身的工作方式几乎总是可以使用,即使已经提交了内部事务。发生这种情况时,下一次使用的会话继续运行,如果它在autocommit = False时启动一个新事务,或者如果autocommit = True则继续“自动提交”模式。基本上它是自动恢复活力。

会话无法继续进行的一次是刷新失败,并且还没有调用rollback()方法,当处于autocommit = False模式时,Session希望您明确地执行flush()失败。要查看Session是否处于此特定状态,session.is_active属性在这种情况下将返回False。

我不能100%确定在使用zope.transaction时继续使用Session的含义是什么。我认为这取决于你如何在更大的方案中使用zope.transaction。

这引出了我们许多这些问题所做的事情,这就是你真正想做的事情。比如,“重新创建必要的模型实例”不是会话所做的事情,除非您指的是已经过期的现有实例(它们的内容已经清空)。只要您访问过任何内容,过期的对象就会通过Session自动从数据库加载新状态,因此无需告知Session在此处执行任何操作。

这当然是一个完全关闭自动过期的选项,但是你甚至在这里遇到问题意味着某些东西不能正常工作。就像你有一些错误信息。需要更多细节才能准确了解您所遇到的问题。