gpt4 book ai didi

ios - 从核心数据中的关系中删除对象的正确方法

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:05:10 24 4
gpt4 key购买 nike

我有一个包含两个实体的简单数据模型:Person 和 Company。一个人可以分到很多公司,一个公司也可以分到很多人。我用 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是清空的(没有对象注册在里面),所以没有理由清除内存中的invalidate relationship,因为内存中没有对象。唯一应该做的事情是上面列出的数据库级删除操作。

这种情况是有问题的,因为当我有 1000 人分配给公司时,删除公司的操作会花费太多时间(以秒计算)。

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

在这里你可以下载为当前问题准备的Xcode工程: Xcode project

最佳答案

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

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

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

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

如果你能等到 iOS 8,你可以做一个批量更新来消除这种关系。

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com