我正在尝试使用金字塔的事务管理器来提交更改。不幸的是,无论我做什么,每次都会回滚。
我尝试过这么简单:
def handle(conn):
conn.execute('''ALTER TABLE ....''')
with bootstrap(sys.argv[1]) as env:
with env['request'].tm:
handle(env['request'].dbsession)
以及下拉到连接和创建显式事务:
def handle(conn):
with conn.begin() as tran:
conn.execute('''ALTER TABLE ....''')
tran.commit()
with bootstrap(sys.argv[1]) as env:
with env['request'].tm:
handle(env['request'].dbsession.connection())
以及其他一些方法,但每次,我都会获得ROLLBACK
而不是COMMIT
。
在第一种情况结束时进行简单提交会导致:
Error: Transaction must be committed using the transaction manager
我很遗憾sqlalchemy在这种情况下实际上做了什么 - 为什么我会通过回滚获得“成功”?我该怎么办?如果handle
内有嵌套的显式事务,它会是什么样子?
答案 0 :(得分:1)
正如ilja在评论中所说,正确的答案是,当您通过ORM操作直接操作连接而不是ORM会话时,zope.sqlalchemy无法知道是否你改变了什么。默认情况下,zope.sqlalchemy要求您使用ORM或标记手动更改的会话。
from zope.sqlalchemy import mark_changed
mark_changed(env['request'].dbsession)
或者,如果这是您的常见模式,那么您可以将zope.sqlalchemy配置为始终假设会话已更改,因此默认情况下会发出提交而不是回滚。
zope.sqlalchemy.register(..., initial_state='changed')
您的代码中已经有这样的调用,您只需要添加initial_state
属性。