Как проверить, существует ли объект в кеше pony orm? - PullRequest
0 голосов
/ 03 июля 2018

Я пытаюсь обработать некоторые данные и затем вставить их за один раз, у таблиц есть несколько составных ключей, которые я использую, чтобы проверить, существует ли запись для этого Id, тогда она должна обновить запись вместо создания.

Хотя при обработке данных существует вероятность того, что один и тот же идентификатор существует в выборочных данных несколько раз, и при обработке он не найдет запись, соответствующую этому идентификатору, в базе данных, поэтому он пытается создать запись каждый раз.

Можно ли как-нибудь проверить кеш на совпадение составного ключа?

1 Ответ

0 голосов
/ 05 июля 2018

Вы можете использовать get метод экземпляра объекта, чтобы найти объект по комбинации значений первичного ключа.

Метод get выполняет поиск в кэше и базе данных db_session и возвращает None, если объект не найден:

from pony import orm

db = orm.Database('sqlite', ':memory:')

class Point(db.Entity):
    x = orm.Required(int)
    y = orm.Required(int)
    description = orm.Optional(str)
    orm.PrimaryKey(x, y)

db.generate_mapping(create_tables=True)

points = [(1, 2, 'foo'), (3, 4, 'bar'), (1, 2, 'baz'), (5, 6, 'qux')]

with orm.db_session:
    for a, b, s in points:
        point = Point.get(x=a, y=b)
        if point is None:
            point = Point(x=a, y=b, description=s)

Метод get также работает с дополнительными составными ключами .

Также вы можете искать экземпляр сущности, используя квадратные скобки и перехватывать исключение:

with orm.db_session:
    try:
        point = Point[10, 20]
    except orm.ObjectNotFound:
        point = Point(x=10, y=20)

Обновление: разъяснения по использованию патерна IdentityMap

PonyORM использует шаблон проектирования IdentityMap. Это означает, что все объекты одного и того же класса, загруженные или созданные внутри db_session, индексируются значениями его первичного ключа. Невозможно несколько объектов одного класса с одним и тем же первичным ключом внутри одного db_session. Если метод get вызывается несколько раз с одним и тем же значением первичного ключа, он возвращает один и тот же экземпляр:

with db_session:
    a = Point.get(x=10, y=20)
    b = Point.get(x=10, y=20)
    assert a is b  # the same object!

То же самое относится к ситуации, когда вы просто создаете объект и затем пытаетесь get объект с тем же первичным ключом: Pony вернет объект, который вы только что создали:

with db_session:
    a = Point.get(x=10, y=20)
    if a is None:
        a = Point(x=10, y=20)

    # later, in the same db_session:
    b = Point.get(x=10, y=20)
    assert a is b  # the same object, not saved yet

С другой стороны, если вы попытаетесь создать два разных объекта с одним и тем же первичным ключом, вы получите сообщение об ошибке:

with db_session:
    a = Point(x=10, y=20)
    b = Point(x=10, y=20)

Traceback (most recent call last):
    ...
pony.orm.core.CacheIndexError: Cannot create Point: instance with primary key 10, 20 already exists

Также, если вы попытаетесь создать объект, который уже существует в базе данных, не проверив его, вы получите ошибку:

with db_session:
    a = Point(x=30, y=40)

with db_session:
    b = Point(x=30, y=40)

Traceback (most recent call last):
    ...
pony.orm.core.TransactionIntegrityError: Object Point[30, 40] cannot be stored in the database. IntegrityError: UNIQUE constraint failed: Point.x, Point.y

Чтобы избежать этой ошибки, вы можете проверить существование объекта с помощью get перед созданием нового.

...