2016-10-03 2 views
0

Как объединить два компонента 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 
+2

Я не могу воспроизвести ваш первый случай. Второй случай ожидается, потому что флеш происходит с фиксацией; если вы выполните 'session.flush()' после 'x.note = 'a'', вы получите ожидаемый результат. – univerio

+0

спасибо @univerio, отредактирован, проблема в первом случае происходит после второго повторного прогона. –

ответ

0

После получения дополнительной информации о session, у меня есть ответ об этом.


session имеет свои рабочие механизмы, один unit of work -

«Все изменения в объекты, поддерживаемые в сессии отслеживаются - прежде чем база данных запрашивается еще раз или до того, как текущая транзакция он сбрасывает все ожидающие изменения в базу данных. Это , известный как шаблон работы. " http://docs.sqlalchemy.org/en/latest/orm/session_basics.html

  • Первая проблема из-за unit of work так что SQLAlchemy будет отслеживать то, что изменяется и бойко делать только то, что действительно необходимо. В результате требуется только одно обновление.

  • Вторая проблема решается с помощью руководства session.flush() обновления ORM, чтобы получить правильный порядок выполнения. Поскольку я использую два независимых механизма SQLAlchemy, и кажется, что unit of work не относится также к необработанному выражению SQL.

Смежные вопросы