Как объединить два компонента SQLAlchemy - Core (SQL Expression) и ORM? У меня есть таблица, которая использует ORM mapper, а другие - только объект Table, и я хочу, чтобы одно соединение и одна транзакция для двух.Комбинировать SQLAlchemy Core и ORM получить проблемы
У меня есть два примера, но возникают проблемы (результат не согласуется с моими запросами, которые чередуют два стиля доступа). Один сеанс autocommit, другой - сеанс по умолчанию.
session_autocommit=Session(bind=db,autocommit=True)
def f():
with session_autocommit.begin() as trans:
# ORM
x=session_autocommit.query(Mytable).filter(Mytable.id==1).first()
# sql expression by SQLAlchemy Core
session_autocommit.execute(mytable.update().where(mytable.c.id==1)\
.values(note=None))
# update via ORM
x.note='a'
f() # ok two update appear in log.
f() # ! only one update as below
x.note == 'a'
# the second run of f() returns False but should be True.
логарифм второго запуска F() говорит, что это только одно обновление (примечание = None), то второе обновление пропущена?
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id, mytable.note AS mytable_note
FROM mytable
WHERE mytable.id = %(id_1)s
LIMIT %(param_1)s
INFO sqlalchemy.engine.base.Engine {'param_1': 1, 'id_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(id_1)s
INFO sqlalchemy.engine.base.Engine {'id_1': 1, 'note': None}
INFO sqlalchemy.engine.base.Engine COMMIT
ОБНОВЛЕНИЕ Вторая проблема решена.
Спасибо комментарий @univerio, мне нужно, чтобы flush
сначала для правильного заказа исполнений. Поскольку я использую два независимых механизма SQLAlchemy.
session=Session(bind=db,autocommit=False)
# default session must rely commit to control transaction.
session.commit()
x=session.query(Mytable).filter(Mytable.id==1).first()
x.note='a'
session.execute(mytable.update().where(mytable.c.id==1)\
.values(note=None))
session.commit()
x.note=='a'
# the test return True but should be None.
В журнале говорится о двух очередном заказе?
INFO sqlalchemy.engine.base.Engine COMMIT
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id, mytable.note AS mytable_note
FROM mytable
WHERE mytable.id = %(id_1)s
LIMIT %(param_1)s
INFO sqlalchemy.engine.base.Engine {'id_1': 1, 'param_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(id_1)s
INFO sqlalchemy.engine.base.Engine {'note': None, 'id_1': 1}
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id
FROM mytable
WHERE mytable.id = %(param_1)s
INFO sqlalchemy.engine.base.Engine {'param_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(mytable_id)s
INFO sqlalchemy.engine.base.Engine {'note': 'a', 'mytable_id': 1}
INFO sqlalchemy.engine.base.Engine COMMIT
Я не могу воспроизвести ваш первый случай. Второй случай ожидается, потому что флеш происходит с фиксацией; если вы выполните 'session.flush()' после 'x.note = 'a'', вы получите ожидаемый результат. – univerio
спасибо @univerio, отредактирован, проблема в первом случае происходит после второго повторного прогона. –