Я предполагаю, что базовая модель данных выглядит следующим образом:
Вопрос 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 оба хороши.