Отношение CoreData ко многим: «addXxxxlist» - как полностью заменить список - PullRequest
1 голос
/ 04 марта 2020

У меня есть Person сущность, которая имеет отношение Contacts ко многим с именем сущности Contact.

CoreData создает для меня свойство NSSet:

@property (nullable, nonatomic, retain) NSSet<Contact *> *contact_list;

Что если мне нужно полностью изменить список контактов этого человека? Могу ли я просто заменить весь набор:

person.contact_list = newContactList

Или я должен всегда использовать сгенерированные CoreData методы доступа и мутаторы? Например:

person.removeContact_list(person.contact_list) // removing all the current contacts
person.addContact_list(newContactList) // setting a new contact list

Может ли прежний подход вызвать ошибки базы данных в конфигурации отношений? Какой предпочтительный способ полностью заменить набор отношений ко многим?

1 Ответ

1 голос
/ 05 марта 2020

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

enter image description here

Вопрос 1 : Могу ли я просто заменить весь набор: person.contact_list = newContactList или я действительно должен всегда использовать сгенерированные CoreData аксессоры и мутаторы?

Ответ : Если все объекты данных ранее сохранялись в базе данных, Базовые данные создают тот же SQL код обновления (я использую Swift здесь, но с Obj C это только синтаксические различия):

Подготовьте некоторые объекты и сохраните их:

    // Create Persons
    let personObjA: Person = Person(context: mainContext)
    personObjA.name = "Person A"
    let personObjB: Person = Person(context: mainContext)
    personObjB.name = "Person B"
    saveContext()
    // Create Contacts
    let contactObj1: Contact = Contact(context: mainContext)
    contactObj1.name = "Contact A"
    let contactObj2: Contact = Contact(context: mainContext)
    contactObj2.name = "Contact B"
    let contactObj3: Contact = Contact(context: mainContext)
    contactObj2.name = "Contact C"
    let contactObj4: Contact = Contact(context: mainContext)
    contactObj2.name = "Contact D"
    saveContext()

Метод путем назначения нового списка контактов:

    // Set Contacts for PersonA
    personObjA.addToContacts([contactObj1,contactObj2])
    saveContext()
    // Replace Contacts for PersonA
    personObjA.contacts = [contactObj3,contactObj4]
    saveContext()

Core Data выполняет этот SQL:

CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: UPDATE OR FAIL ZPERSON SET Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)3
CoreData: details: SQLite bind[1] = (int64)1
CoreData: details: SQLite bind[2] = (int64)2
CoreData: sql: UPDATE OR FAIL ZCONTACT SET Z2CONTACTS = ?, Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)1
CoreData: details: SQLite bind[1] = (int64)2
CoreData: details: SQLite bind[2] = (int64)2
CoreData: details: SQLite bind[3] = (int64)1
CoreData: sql: UPDATE OR FAIL ZCONTACT SET Z2CONTACTS = ?, Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)1
CoreData: details: SQLite bind[1] = (int64)2
CoreData: details: SQLite bind[2] = (int64)3
CoreData: details: SQLite bind[3] = (int64)1
CoreData: sql: COMMIT

Метод с использованием Core Средства доступа к данным и мутаторы:

    // Set Contacts for PersonB
    personObjB.addToContacts([contactObj1,contactObj2])
    saveContext()
    // Replace Contacts for PersonB
    personObjB.removeFromContacts([contactObj1,contactObj2])
    personObjB.addToContacts([contactObj3,contactObj4])
    saveContext()

Базовые данные будут выполняться SQL следующим образом:

CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: UPDATE OR FAIL ZPERSON SET Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)3
CoreData: details: SQLite bind[1] = (int64)2
CoreData: details: SQLite bind[2] = (int64)2
CoreData: sql: UPDATE OR FAIL ZCONTACT SET Z2CONTACTS = ?, Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)2
CoreData: details: SQLite bind[1] = (int64)3
CoreData: details: SQLite bind[2] = (int64)2
CoreData: details: SQLite bind[3] = (int64)2
CoreData: sql: UPDATE OR FAIL ZCONTACT SET Z2CONTACTS = ?, Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: details: SQLite bind[0] = (int64)2
CoreData: details: SQLite bind[1] = (int64)3
CoreData: details: SQLite bind[2] = (int64)3
CoreData: details: SQLite bind[3] = (int64)2
CoreData: sql: COMMIT

Вопрос 2 : Может ли прежний подход вызывает ошибки базы данных в конфигурации отношений?

Ответ : если все простые обновления выполняются в тот же поток, тот же контекст (...), как описано в предыдущем ответе на вопрос 1, в отношениях не будет ошибок.

Вопрос 3 : Какой предпочтительный способ полностью заменить набор отношений «ко-многим»?

Ответ : Если в одном потоке выполняются простые шаги обновления, тот же контекст (...), как описано в предыдущем ответе на вопрос 1 оба хороши.

...