OGeek|极客世界-中国程序员成长平台

标题: ios - 从核心数据中的关系中删除对象的正确方法 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-12 10:24
标题: ios - 从核心数据中的关系中删除对象的正确方法

我有一个包含两个实体的简单数据模型:个人和公司。一个人可以分配给很多公司,一个公司可以分配给很多人。我已经用 1 家公司和 2 个人填充了数据库,并将所有人分配给公司。在填充数据库的过程中,Core Data 会生成如下所示的日志:

CoreData: sql: INSERT INTO ZCOMPANY(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)
CoreData: sql: INSERT OR REPLACE INTO Z_1PERSONS(Z_1COMPANIES, Z_2PERSONS) VALUES (1, 2)
CoreData: sql: INSERT OR REPLACE INTO Z_1PERSONS(Z_1COMPANIES, Z_2PERSONS) VALUES (1, 1)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZNAME) VALUES(?, ?, ?, ?)

接下来我关闭应用程序,再次启动它并删除公司。然后Core Data执行以下操作:

CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZPERSON t0 ON t0.Z_PK = t1.Z_2PERSONS WHERE t1.Z_1COMPANIES = ? 
CoreData: annotation: sql connection fetch time: 0.0009s
CoreData: annotation: total fetch execution time: 0.0018s for 2 rows.
CoreData: annotation: to-many relationship fault "persons" for objectID 0x8d281e0 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Company/p1> fulfilled from database.
Got 2 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHERE  t0.Z_PK = ? 
CoreData: annotation: sql connection fetch time: 0.0008s
CoreData: annotation: total fetch execution time: 0.0016s for 1 rows.
CoreData: annotation: fault fulfilled from database for : 0x8e19940 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1>
CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZCOMPANY t0 ON t0.Z_PK = t1.Z_1COMPANIES WHERE t1.Z_2PERSONS = ? 
CoreData: annotation: sql connection fetch time: 0.0009s
CoreData: annotation: total fetch execution time: 0.0022s for 1 rows.
CoreData: annotation: to-many relationship fault "companies" for objectID 0x8e19940 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1> fulfilled from database.
Got 1 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHERE  t0.Z_PK = ? 
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0014s for 1 rows.
CoreData: annotation: fault fulfilled from database for : 0x8e18f90 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2>
CoreData: sql: SELECT 0, t0.Z_PK FROM Z_1PERSONS t1 JOIN ZCOMPANY t0 ON t0.Z_PK = t1.Z_1COMPANIES WHERE t1.Z_2PERSONS = ? 
CoreData: annotation: sql connection fetch time: 0.0006s
CoreData: annotation: total fetch execution time: 0.0015s for 1 rows.
CoreData: annotation: to-many relationship fault "companies" for objectID 0x8e18f90 <x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2> fulfilled from database.
Got 1 rows
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: DELETE FROM ZCOMPANY WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: DELETE FROM Z_1PERSONS WHERE Z_1COMPANIES = 1
CoreData: sql: UPDATE ZPERSON SET Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: UPDATE ZPERSON SET Z_OPT = ?  WHERE Z_PK = ? AND Z_OPT = ?
CoreData: sql: COMMIT

正如我们所见,Core Data 从数据库中获取分配给已删除公司的所有人员。接下来,它为每个人获取公司集合。最终预期的删除操作在数据库上执行:

DELETE FROM ZCOMPANY WHERE Z_PK = ? AND Z_OPT = ?
DELETE FROM Z_1PERSONS WHERE Z_1COMPANIES = 1

当我删除公司时,一个 managedObjectContext 是清除的(其中没有注册对象),因此没有理由清除内存中的无效关系,因为内存中没有对象。唯一应该做的是上面列出的数据库级删除操作。

情况有问题,因为当我有1000人分配到公司时,删除公司的操作需要太多时间(以秒计)。

删除只执行必要操作并确保数据一致性的公司的正确方法是什么?

您可以在这里下载为解决问题而准备的 Xcode 项目: Xcode project



Best Answer-推荐答案


Core Data 不是数据库。 Core Data 是一个可以保存到数据库的对象层次结构。

在这种情况下,这是一个重要的区别。当您删除某些内容时,Core Data 将检索关系两侧的对象,以确保保留引用完整性。使用 SQLite,这似乎效率低下(确实如此)。当商店是其他东西时,需要仔细检查。

那么,如何解决这个问题?一是承认删除需要一些时间并启动一个后台私有(private)队列来处理删除。不是最优的。

另一种选择是在这两个表之间使用软引用。同样不理想。

如果您可以等到 iOS 8,您可以进行批量更新以消除关系。

关于ios - 从核心数据中的关系中删除对象的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24265742/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4