【问题标题】:SQLAlchemy: use related object when session is closedSQLAlchemy:会话关闭时使用相关对象
【发布时间】:2020-12-26 14:43:46
【问题描述】:

我有许多模型必须使用彼此之间的关系链接。我的代码is very complicated 所以我无法在查询后保持会话活跃。相反,我尝试预加载所有对象:

def db_get_structure():
    with Session(my_engine) as session:
        deps = {x.id: x for x in session.query(Department).all()}
        ...
        return (deps, ...)

def some_logic(id):
    struct = db_get_structure()
    return some_other_logic(struct.deps[id].owner)

但是,不管所有对象都已加载,我还是会收到以下错误:

sqlalchemy.orm.exc.DetachedInstanceError:父实例 未绑定到会话;属性“所有者”的延迟加载操作无法继续

是否可以将预加载的对象相互链接,以便在会话关闭后关系仍然有效?

我知道joined queries (.options(joinedload(),但是这种方法会导致更多的代码行和更大的数据库请求,我认为这应该更简单地解决,因为所有对象都已经加载到 Python 对象中。 现在甚至可以请求像struct.deps[struct.deps[id].owner_id] 这样的相关对象,但我认为ORM 应该这样做并使用一些“缓存加载”提供更短的符号struct.deps[id].owner

【问题讨论】:

    标签: python session orm sqlalchemy


    【解决方案1】:

    每当您访问尚未从数据库加载的数据库实体上的属性时,SQLAlchemy 都会向数据库发出隐式 SQL 语句以获取该数据。我的猜测是当你发出 struct.deps[struct.deps[id].owner_id] 时会发生这种情况。

    如果相关对象已从会话中删除,则它处于“分离”状态,SQLAlchemy 可防止您意外遇到不一致的数据。为了再次使用该对象,它需要“重新附加”。

    我已经经常使用session.merge

    attached_object = new_session.merge(detached_object)
    

    但这将使对象实例与数据库协调,并可能在必要时对数据库进行更新。 detached_object 被视为“真相”。

    相信您可以使用session.refresh(detached_object) 进行相反的操作(通过从数据库读取而不是写入数据库来附加它),但我需要验证这一点。如果我发现了什么,我会更新帖子。

    两种方式必须通过select 至少与数据库通信以确保数据一致。

    为了避免加载,发出session.merge(..., load=False)。但这有一些非常重要的警告。详情请查看session.merge() 的文档。

    我需要阅读您添加的有关“复杂代码”的链接。我想了解为什么您需要以您的方式丢弃您的会话。也许有更简单的方法?

    【讨论】:

    • 您好,感谢您的回复!恐怕你还没有完全理解我的问题。我不需要在提取所有数据后处理数据库,并且新鲜度并不重要(数据很少更新)。我需要的是在对象之间建立链接。请注意,我从数据库中预加载了 all 对象,我只是希望能够编写 struct.deps[id].owner 这暂时不起作用,尽管短语 struct.deps[struct.deps[id].owner_id] 有效,因为我拥有所有对象我需要,但不需要它们之间的链接。
    • 关闭会话的主要原因是我的代码非常并发和分叉,不关闭会话就会变成地狱。第二个原因是我不想混合抽象级别:数据库工作和业务逻辑。另一个原因是理论上不需要执行后续查询,因为所有对象都已经在这里。
    • 对了。我现在明白你的意思了。不幸的是,我为此不知所措。我会假设它会通过会话身份工作。您是否尝试创建一个新会话并使用session.add() 转储对象(没有调用session.commit() 或课程)?甚至应该可以使用未绑定到数据库的会话以避免事故。
    猜你喜欢
    • 2014-03-11
    • 2020-08-06
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    相关资源
    最近更新 更多