就像许多其他人一样,我遇到了实例未绑定到会话的问题。我已经阅读了 SQLAlchemy 文档和这里的前 10 个问题。不幸的是,我还没有找到对我的错误的解释或解决方案。
我的猜测是 commit() 关闭会话,呈现对象未绑定。这是否意味着需要创建两个对象,一个用于 SQL Alchemy,另一个用于我的其余代码?
我创建一个像这样的对象:
class Mod(Base):
__tablename__ = 'mod'
insert_timestamp = Column(DateTime, default=datetime.datetime.now())
name = Column(String, nullable=False)
Run Code Online (Sandbox Code Playgroud)
然后我使用此函数将其添加到数据库中,之后该对象就没用了,我无法再用它做任何事情,总是收到它未绑定到会话的错误。我尝试保持会话打开、关闭、复制对象、打开两个会话、返回对象、返回对象的副本。
def add(self, dataobjects: list[Base]) -> bool:
s = self.sessionmaker()
try:
s.add_all(dataobjects)
except TypeError:
s.rollback()
raise
else:
s.commit()
return True
Run Code Online (Sandbox Code Playgroud)
这是我的会话设置:
self.engine = create_engine(f"sqlite:///{self.config.database['file']}")
self.sessionmaker = sessionmaker(bind=self.engine)
Base.metadata.bind = self.engine
Run Code Online (Sandbox Code Playgroud)
我的最后一招是为每个对象创建两次,一次用于 SQL Alchemy,一次这样我可以在代码中实际使用该对象。这违背了 SQL Alchemy 对我的目的。
ORM 实体在提交时就会过期。默认情况下,如果在过期后访问实体属性,会话会发出 aSELECT以从数据库获取当前值。在这种情况下,会话仅存在于方法的范围内add,因此后续属性访问会引发“未绑定到会话”错误。
有几种方法可以解决这个问题:
expire _on_commit=False创建会话时通过。这将防止自动过期,因此属性值在离开函数后仍可访问add,但它们可能已过时。add并将其作为参数传递(或从 中返回它add,尽管这相当难看)。只要会话没有被垃圾回收,实体就保持与其绑定。mod = session.merge(mod)每个实体执行将其绑定到新会话的操作。您选择哪个选项取决于您的应用程序。
| 归档时间: |
|
| 查看次数: |
4355 次 |
| 最近记录: |