SQLAlchemy,将对象绑定到Session

时间:2011-11-24 08:21:41

标签: python sqlalchemy

由于各种原因,我试图从数据库中获取对象集合,并将其传递给另一个未连接到数据库的进程。我的代码看起来像下面的那个,但我一直在

sqlalchemy.exc.UnboundExecutionError: Instance <MyClass at 0x8db7fec> is not bound to a Session; attribute refresh operation cannot proceed

当我尝试在get_list()方法之外查看列表中的元素时。

def get_list (obj):
    sesson = Session()
    lst = session.query(MyClass).all()
    session.close()
    return lst

但是,如果我使用这个

def get_list_bis (obj)
    session = Session()
    return session.query(MyClass).all()

我可以使用这些元素,但担心会话的状态,因为它没有关闭。

我在这里缺少什么?

3 个答案:

答案 0 :(得分:57)

如果您希望通过查询会话生成的一堆对象在会话范围之外可用,则需要expunge它们用于会话。

在您的第一个功能示例中,您需要添加一行:

session.expunge_all()

session.close()

更一般地说,假设会话没有立即关闭,就像第一个例子中一样。也许这是一个在Web请求的整个持续时间内保持活动的会话或类似的东西。在这种情况下,您不希望expunge_all。你会想要更多的手术:

for item in lst:
    session.expunge(item)

答案 1 :(得分:9)

这通常是由于对象处于expired状态,对象在committing之后过期,然后当这些过期的对象即将被使用时,ORM尝试到refresh他们,但是当对象从会话中分离时,这是不可能的(因为该会话是例如关闭)。可以通过使用expire_on_commit=False param。

创建会话来管理此行为
>>> from sqlalchemy import inspect
>>> insp = inspect(my_object)
>>> insp.expired
True  # then it will be refreshed...

答案 2 :(得分:1)

在我的情况下,我也保存了一个相关的实体,这个配方帮助我refresh会话中的所有实例,利用Session可迭代的事实:

map(session.refresh, iter(session))  # call refresh() on every instance

这是非常无效的,但有效。单元测试应该没问题。

最后注意:在Python3中map()是一个生成器,不会做任何事情。使用列表推导的实际循环