CoreData 对多关系:"addXxxxlist" - 如何完全替换列表

CoreData to-many relationship: "addXxxxlist" - how to replace the list completely

我有一个 Person 实体,它与实体名称 ContactContacts 对多关系。

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我可以只替换整个集合吗:person.contact_list = newContactList 还是我应该始终使用 CoreData 生成的访问器和修改器?

答案:如果所有数据对象以前都保存在数据库中,Core Data 会创建相同的 SQL 更新代码(我正在使用 Swift在这里但与 ObjC 只是语法差异):

准备一些对象并保存:

    // 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()

核心数据执行此 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 Data访问器和修改器的方法:

    // 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 的前一个答案中描述的相同上下文 (...) 都很好。