【发布时间】:2018-01-13 13:41:37
【问题描述】:
所以我在没有太多上下文的情况下提出了这个问题,并且被否决了,让我们再试一次......
首先,我不遵循 SQLAlchemy 的 session.add 背后的逻辑。我知道它将对象排队以进行插入,并且我知道session.query 在连接的数据库中而不是在会话中查找,但是在 SQLAlchemy 中是否有可能在不先执行session.flush 的情况下查询会话?我对 session.query 的期望是它查询会话...
我现在在None 来自session.query().first() 之后手动查找session.new。
我不想在session.flush 之前做session.flush 有两个原因,
- 基于效率的担忧(如果我仍在用户可能想要回滚的会话中,我为什么要写入数据库并查询数据库?);
- 二是因为我采用了fairly large program,它设法定义了自己的
Session,其实例导致flush也提交。
所以这个问题的真正核心是,谁在帮我在 github 上的 GPL 程序中找到错误!
这是一个代码 sn-p,在 bauble/ghini 中有一个令人惊讶的行为:
# setting up things in ghini
# <replace-later>
import bauble
import bauble.db as db
db.open('sqlite:///:memory:', verify=False)
from bauble.prefs import prefs
import bauble.pluginmgr as pluginmgr
prefs.init()
prefs.testing = True
pluginmgr.load()
db.create(True)
Session = bauble.db.Session
from bauble.plugins.garden import Location
# </replace-later>
# now just plain straightforward usage
session = Session()
session.query(Location).delete()
session.commit()
u0 = session.query(Location).filter_by(code=u'mario').first()
print u0
u1 = Location(code=u'mario')
session.add(u1)
session.flush()
u2 = session.query(Location).filter_by(code=u'mario').one()
print u1, u2, u1==u2
session.rollback()
u3 = session.query(Location).filter_by(code=u'mario').first()
print u3
这里的输出是:
None
mario mario True
mario
这里有我认为只是设置数据库的标准简单代码:
from sqlalchemy import Column, Unicode
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Location(Base):
__tablename__ = 'location'
code = Column(Unicode(64), index=True, primary_key=True)
def __init__(self, code=None):
self.code = code
def __repr__(self):
return self.code
from sqlalchemy import create_engine
engine = create_engine('sqlite:///joindemo.db')
Base.metadata.create_all(engine)
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine, autoflush=False)
有了这个,上面同样的代码 sn-p 的输出就不那么令人惊讶了:
None
mario mario True
None
【问题讨论】:
-
您已禁用 autoflush,因此您的
mario, none, False可以正常工作。 针对数据库触发查询,如果您不手动或自动将会话中保存的更改刷新到数据库,则查询无法看到这些更改。而且flush并不意味着提交,所以还有其他事情发生了,你应该提供一个minimal reproducible example关于这个,或者通过“回滚不起作用”来更清楚你的意思。 -
我禁用了 autoflush,因为正如您也提到的,我试图生成一个 Minimal 示例,从 a program I adopted 开始,其中单元测试依赖于禁用 autoflush。
-
»flush 并不意味着提交,所以还有其他事情发生«,我试图在 ghini.desktop 代码中查找它,但我不认识它。并且该代码远非 Minimal。
-
»对 DB 触发查询« — 因为
query是会话的一种方法,我假设我正在查询会话,所以令我惊讶的是session.query不返回对象在session.new. -
如果有人想帮我看看deeper in the code?谢谢。
标签: python transactions sqlalchemy