SQLАлхимия:Сопоставления объектов потеряны после фиксации?

StackOverflow https://stackoverflow.com/questions/1033199

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня возникла простая проблема в SQLAlchemy.У меня есть одна модель в таблице, назовем ее здесь Модель1.Я хочу добавить строку в эту таблицу и получить автоинкрементируемый ключ, чтобы я мог создать с ее помощью другую модель и использовать этот ключ.Это не ошибочный дизайн базы данных (отношение 1:1 и т. д.).Мне просто нужен этот ключ в другой таблице, потому что другая таблица передается на удаленный хост, и мне нужны совпадающие ключи, чтобы серверы понимали друг друга.Между этими двумя таблицами больше не будет локальных ссылок, и из-за этого также невозможно создавать связи.

Рассмотрим следующий код:

object1 = model.Model1(param)
DBSession.add(object1)

# if I do this, the line below fails with an UnboundExecutionError.
# and if I dont do this, object1.id won't be set yet
#transaction.commit()

object2 = model.AnotherModel(object1.id) #id holds the primary, autoincremented key

Мне хотелось бы, чтобы мне даже не приходилось совершать коммит «вручную».По сути, я хотел бы добиться того, чтобы «Model1» постоянно росла с увеличением первичного ключа Model.id.AnotherModel — это всегда лишь небольшая часть Model1, которая еще не обработана.Конечно, я мог бы добавить флаг в «Модель1», логическое поле таблицы, чтобы отмечать уже обработанные элементы, но я надеялся, что в этом нет необходимости.

Как я могу заставить мой приведенный выше код работать?

Приветствую,

Том

Это было полезно?

Решение

Пара вещей:

  • Не могли бы вы объяснить, что такое переменная transaction связан с?
  • Какой именно оператор вызывает ошибку UnboundExecutionError?
  • Предоставьте полное сообщение об исключении, включая трассировку стека.
  • «Нормальным» поступком в этом случае было бы вызвать DBSession.flush().Вы пробовали это?

Пример:

object1 = Model1(param)
DBSession.add(object1)
DBSession.flush()
assert object1.id != None # flushing the session populates the id

object2 = AnotherModel(object1.id)

За отличное объяснение сеанса SA и того, что flush() делает, см. Использование сеанса.

По сути, flush() заставляет ожидающие экземпляры становиться постоянными - это означает, что новые объекты вставляются в таблицы базы данных. flush() также ОБНОВЛЯЕТ таблицы значениями для экземпляров, которые отслеживает сеанс и в которых есть изменения.

commit() всегда проблемы flush() первый.

В рамках транзакции вы можете сбрасывать данные несколько раз.Каждый методlush() вызывает UPDATE и/или INSERT в базе данных.Всю транзакцию можно зафиксировать или откатить.

Другие советы

если вы хотите, чтобы новые идентификаторы первичного ключа генерировались без какой-либо фиксации, просто вызовите session.flush().Это отправит все ожидающие в базу данных данные в рамках текущей транзакции.

Я использовал это только с ForeignKeys, поэтому во втором случае вы бы предпочли использовать model.AnotherModel(model1=object1), и тогда это просто сработало (тм).Я подозреваю, что это может быть проблема с вашими моделями, так что, возможно, вы могли бы опубликовать и их?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top