Алхимия SQL: SAПредупреждение: карта идентификаторов уже имеет идентификатор для (<класс>), заменяя его новым очищенным Python

Программы на Python
Ответить
Anonymous
 Алхимия SQL: SAПредупреждение: карта идентификаторов уже имеет идентификатор для (<класс>), заменяя его новым очищенным

Сообщение Anonymous »

Я использую SQLAlchemy с MySQL для вставки строк в таблицу БД. В некоторых случаях я могу попытаться вставить ту же строку еще раз, поэтому у меня есть прослушиватель событий before_execute, целью которого является предотвращение исключений OnDuplateKey. Слушатель выглядит так:

Код: Выделить всё

# Intercept calls for Insert and add IGNORE to the generated SQL
@event.listens_for(Engine, 'before_execute', retval=True)
def _ignore_insert(conn, element, multiparams, params, execution_options):
# Check that this is an Insert call, and that the current Insert call is meant for a table which we want to add
# the IGNORE keyword to
if str(conn.engine.url).startswith('sqlite'):
# Avoid generating illegal SQL syntax for sqlite DBs
return element, multiparams, params
if isinstance(element, Insert) and 'ignore_tables' in conn.info and element.table.name in conn.info[
'ignore_tables']:
element = element.prefix_with('IGNORE')
return element, multiparams, params
Реализация оболочки была взята из этого ответа.
Эта оболочка работает отлично, но каждый раз, когда я пытаюсь вставить строку, которая уже существует в БД, будет выдано предупреждение:

Код: Выделить всё

SAWarning: Identity map already had an identity for (, (0,), None), replacing it with newly flushed object.   Are there load operations occurring inside of an event handler within the flush?
В 99% случаев я могу спокойно игнорировать это предупреждение, поскольку после сохранения объекта мне не нужно снова читать его в том же сеансе SQLAlchemy.
Но бывает редкий случай, когда я хочу прочитать объект еще раз, и если я попытаюсь прочитать его, я получу следующее исключение:

Код: Выделить всё

sqlalchemy.orm.exc.ObjectDeletedError: Instance '
' has been deleted, or its row is otherwise not present.
Если присмотреться к самому сеансу и свойствуident_map, то видно, что даже если я храню очень большое количество уже существующих строк (даже более 500 строк), , только для одной из этих строк будет выдано это предупреждение, и только одна будет недоступна, я могу это заметить, посмотрев наident_map и увижу, что только тот объект, на который было выдано предупреждение for появляется в свойствеident_map._dict.
Конечно, если я проверю, существует ли строка в БД, прежде чем пытаться ее сохранить (таким образом избегая фиксации строк которые уже существуют), никаких предупреждений не выдается вообще, но такая проверка очень затратна, поэтому я хотел бы продолжать использовать свою обертку без возникновения предупреждений и исключений.
Любой идея, почему это может произойти и как этого избежать? Я уже пробовал использовать session.refresh(), но это также вызывает исключение, то же самое для session.merge(). session.expunge() и session.flush() в этом сценарии ничего не делают.

Подробнее здесь: https://stackoverflow.com/questions/699 ... -class-rep
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»