如何解决SQLAlchemy:会话关闭时使用相关对象
我有许多必须相互使用关系链接的模型。我的代码为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:父实例未绑定到Session;属性“所有者”的延迟加载操作无法进行
是否可以将预加载的对象彼此链接,以便在会话关闭后该关系能够正常工作?
我了解joined queries(.options(joinedload(
),但是这种方法会导致更多的代码行和更大的DB请求,而且我认为应该更简单地解决此问题,因为所有对象均已加载到Python中对象。
现在甚至可以请求诸如struct.deps[struct.deps[id].owner_id]
之类的相关对象,但是我认为ORM应该这样做,并使用一些“缓存的负载”来提供较短的表示法struct.deps[id].owner
。
解决方法
无论何时访问尚未从数据库加载的数据库实体上的属性,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()的文档。
我将需要阅读您添加的有关“复杂代码”的链接。我想了解为什么您需要以这种方式放弃会议。也许有一种更简单的方法?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。