SQLAlchemy中scoped_session的问题-它如何工作?


问题内容

我不太确定scoped_session是如何工作的,除了似乎是一个包装程序,它隐藏了几个真实的会话,使它们针对不同的请求而分开。它是否使用线程局部变量执行此操作?

无论如何,问题如下:

S = elixir.session # = scoped_session(...)
f = Foo(bar=1)
S.add(f) # ERROR, f is already attached to session (different session)

不知道f是如何在另一个会话中结束的,我以前没有遇到过问题。在其他地方,我的代码看起来像这样,但实际上可以工作。如您所料,我感到非常困惑。

我在这里什么都不知道,f似乎已经神奇地添加到了构造函数中的会话中,但是我似乎没有对其使用的会话的任何引用。为什么会在另一个会话中结束?我怎样才能使它结束正确的会议?无论如何,scoped_session是如何工作的?有时似乎只是工作,而有时却无效。

我肯定很困惑。


问题答案:

作用域会话将创建一个代理对象,该对象保留(默认情况下)每个线程会话对象的注册表(默认情况下),这些对象是从传递的会话工厂按需创建的。当您访问诸如此类的会话方法时,ScopedSession.add它将找到与当前线程相对应的会话,并返回add绑定到该会话的方法。使用该ScopedSession.remove()方法可以删除活动会话。

ScopedSession有一些便捷的方法,一种是query_property创建一个属性,该属性返回绑定到在其上创建的作用域会话和被访问的类的查询对象的查询对象。另一个是ScopedSession.mapper添加默认__init__(**kwargs)
构造函数,默认情况下将创建的对象添加到已创建映射器的作用域会话中。可以通过save_on_init映射器的关键字参数来控制此行为。ScopedSession.mapper由于问题中的问题而被弃用。在这种情况下,Python的“显式优于隐式”哲学才真正适用。不幸的是,Elixir仍然默认使用ScopedSession.mapper