菜鸟教程小白 发表于 2022-12-12 10:24:47

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


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

<pre><code>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(?, ?, ?, ?)
</code></pre>

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

<pre><code>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 &#34;persons&#34; for objectID 0x8d281e0 &lt;x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Company/p1&gt; fulfilled from database.
Got 2 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHEREt0.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 &lt;x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1&gt;
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 &#34;companies&#34; for objectID 0x8e19940 &lt;x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p1&gt; fulfilled from database.
Got 1 rows
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME FROM ZPERSON t0 WHEREt0.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 &lt;x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2&gt;
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 &#34;companies&#34; for objectID 0x8e18f90 &lt;x-coredata://0AFFC353-8C34-43AD-8D30-4483FB44BEA4/Person/p2&gt; 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
</code></pre>

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

<pre><code>DELETE FROM ZCOMPANY WHERE Z_PK = ? AND Z_OPT = ?
DELETE FROM Z_1PERSONS WHERE Z_1COMPANIES = 1
</code></pre>

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

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

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

<p>您可以在这里下载为解决问题而准备的 Xcode 项目:
<a href="https://www.dropbox.com/s/f7obv56aks2fa2d/PersonRelationship.zip" rel="noreferrer noopener nofollow">Xcode project</a> </p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>Core Data 不是数据库。 Core Data 是一个<strong>可以</strong>保存到数据库的对象层次结构。</p>

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

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

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

<p>如果您可以等到 iOS 8,您可以进行批量更新以消除关系。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 从核心数据中的关系中删除对象的正确方法,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/24265742/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/24265742/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 从核心数据中的关系中删除对象的正确方法