关于在sqlalchemy会话中刷新对象

Cri*_*rez 21 python mysql session notifications sqlalchemy

好吧,我正在处理有关sqlalchemy和物品令人耳目一新的疑问!

我处于我有2个会话的情况,并且在两个会话中都查询了相同的对象!...对于某些特定的事情,我无法关闭其中一个会话.我修改了对象并在会话A中提交了更改,但在会话B中,属性是最初的属性!没有修改!..

那么......我应该实现某种通知系统来传达变化,还是有一种内置的方式来实现这一点在sqlalchemy?

Mar*_*eth 38

会话旨在像这样工作.会话B中对象的属性将保留在会话B中首次查询时的对象.此外,SQLAlchemy在更改时不会尝试自动刷新其他会话中的对象,也不认为尝试创建某些对象是明智的像这样.

您应该积极地将每个会话的生命周期视为数据库中的单个事务.会话如何以及何时需要处理其对象可能过时的事实并不是一个技术问题,可以通过SQLAlchemy(或SQLAlchemy的任何扩展)中内置的算法来解决:这是一个"业务"问题,您必须解决它的问题确定并编码自己."正确"的响应可能是说这不是问题:如果在会话B启动时使用了数据,则会话B发生的逻辑可能是有效的.你的"问题"实际上可能不是问题.文档实际上有关于何时使用会话整个部分,但如果您希望获得一个通用的解决方案,它会给出相当严峻的响应......

会话通常在逻辑操作开始时构建,其中可能预期数据库访问.

会话,无论何时用于与数据库通信,都会在开始通信时立即开始数据库事务.假设autocommit标志保持其建议的默认值False,则此事务将继续进行,直到会话回滚,提交或关闭.如果在先前的交易结束之后再次使用会话,则会话将开始新的交易; 由此得出,会话能够在许多交易中具有生命周期,尽管一次只能有一个交易.我们将这两个概念称为事务范围和会话范围.

这里的含义是SQLAlchemy ORM鼓励开发人员在他或她的应用程序中建立这两个范围,不仅包括范围的开始和结束,还包括这些范围的扩展,例如,如果单个Session实例是本地的对于函数或方法中的执行流程,它应该是整个应用程序使用的全局对象,还是介于这两者之间的某个位置.

开发人员确定此范围的负担是SQLAlchemy ORM必须对如何使用数据库有强烈意见的一个方面.工作单元格式具体是随着时间的推移累积变化并定期刷新它们之一,使内存状态与已知在本地事务中存在的内容保持同步.此模式仅在有意义的事务范围到位时才有效.

也就是说,您可以采取一些措施来改变这种情况:

首先,您可以减少会话保持打开的时间.会话B正在查询对象,之后您正在使用该对象(在同一会话中)执行某些操作,以使属性保持最新.一种解决方案是在单独的会话中完成第二个操作.

另一种是使用expire/refresh方法,正如文档所示 ......

# immediately re-load attributes on obj1, obj2
session.refresh(obj1)
session.refresh(obj2)

# expire objects obj1, obj2, attributes will be reloaded
# on the next access:
session.expire(obj1)
session.expire(obj2)
Run Code Online (Sandbox Code Playgroud)

您可以使用session.refresh()立即获取对象的最新版本,即使会话早先已经查询过该对象.


Nat*_*les 8

我刚刚遇到了这个问题,现有的解决方案由于某种原因对我不起作用。起作用的是调用session.commit(). 调用之后,该对象具有来自数据库的更新值。

  • 我也是。我认为过期/刷新工作在 ORM 级别而不是事务级别。这使得过期/刷新在其他事务提交的情况下无效。必须提交/回滚才能看到新数据。 (2认同)
  • 优秀、简单的解决方案!正如其他人指出的那样,“session.expire_all()”在单独会话的情况下不起作用。 (2认同)

小智 5

运行此命令,以强制会话更新您选择的数据库中的最新值:

session.expire_all()
Run Code Online (Sandbox Code Playgroud)

关于会话的默认行为和寿命的出色DOC