Код: Выделить всё
# 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?
Но бывает редкий случай, когда я хочу прочитать объект еще раз, и если я попытаюсь прочитать его, я получу следующее исключение:
Код: Выделить всё
sqlalchemy.orm.exc.ObjectDeletedError: Instance '
' has been deleted, or its row is otherwise not present.
Конечно, если я проверю, существует ли строка в БД, прежде чем пытаться ее сохранить (таким образом избегая фиксации строк которые уже существуют), никаких предупреждений не выдается вообще, но такая проверка очень затратна, поэтому я хотел бы продолжать использовать свою обертку без возникновения предупреждений и исключений.
Любой идея, почему это может произойти и как этого избежать? Я уже пробовал использовать session.refresh(), но это также вызывает исключение, то же самое для session.merge(). session.expunge() и session.flush() в этом сценарии ничего не делают.
Подробнее здесь: https://stackoverflow.com/questions/699 ... -class-rep
Мобильная версия