CoreData 对多关系:"addXxxxlist" - 如何完全替换列表
CoreData to-many relationship: "addXxxxlist" - how to replace the list completely
我有一个 Person
实体,它与实体名称 Contact
有 Contacts
对多关系。
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 的前一个答案中描述的相同上下文 (...) 都很好。
我有一个 Person
实体,它与实体名称 Contact
有 Contacts
对多关系。
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 的前一个答案中描述的相同上下文 (...) 都很好。