在 Core Data 中执行子获取时,在父上下文中修改托管对象是不是会向下传播到子上下文?

Posted

技术标签:

【中文标题】在 Core Data 中执行子获取时,在父上下文中修改托管对象是不是会向下传播到子上下文?【英文标题】:Does modifying a managed object in a parent context propagate down to child contexts when performing a child fetch in Core Data?在 Core Data 中执行子获取时,在父上下文中修改托管对象是否会向下传播到子上下文? 【发布时间】:2014-08-07 01:15:25 【问题描述】:

我在 Core Data 的子父上下文中设置了 2 个 NSManagedContext。

    _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_mainContext setParentContext:_parentContext];
    [_mainContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

    _importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_importContext setParentContext:_mainContext];
    [_importContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

如果我按顺序执行以下命令会发生什么(“fetch”表示 NSFetchRequest):

    在 mainContext 中获取托管对象 A。 在 importContext 中获取托管对象 A。 在 mainContext 中更新对象 A。 在 importContext 中获取托管对象 A。

importContext (child) -> mainContext (parent) -> Persist Store Coordinator

我的问题是,在第 4 步中,在 importContext 中获取的对象是否具有我在第 3 步中在 mainContext 中所做的更新更改?阅读网络上的文章似乎表明,如果子上下文已经获取数据(因为缓存了上下文?),则在 parentContext 中所做的更改不会传播到子上下文。

【问题讨论】:

【参考方案1】:

子上下文的更改会在保存子节点时传播给父节点,而不是在获取期间。变化不会朝另一个方向发展。

在你的场景中...

在 mainContext 中获取托管对象 A。

ma​​inContext 将针对其NSPersistentStoreCoordinator 执行提取请求。协调器将找到应该为请求提供服务的存储并为其提供获取。持久存储将返回一个结果,并根据存储保留行数据的内存副本。 ma​​inContext 现在将拥有该对象的内存副本(但不一定是它的任何属性值)。

在 importContext 中获取托管对象 A。

importContext 没有对该对象的内存引用,因此它会将 fetch 传递给它的父对象 ma​​inContextma​​inContext 会将引用传回它的内存对象 A。如果 ma​​inContext 之前没有获取该对象,或者如果它变成了一个错误,ma​​inContext 会一直获取到持久存储。 Fetches 和 objectWithID: 只进行所需的级别。

在 mainContext 中更新对象 A。

ma​​inContext中的内存对象A发生了变化。

在 importContext 中获取托管对象 A。

返回importContext中的内存对象A。在 mainContext 中所做的更改不会出现在此对象中。

请务必记住,创建上下文时,它是其父级状态的“快照”。除非子项以某种方式无效(即故障或丢弃),否则对父项的后续更改将不会在子项中可见。

You can see how changes propogate in this animation.

【讨论】:

我刚刚偶然发现了这个问题。似乎很奇怪,更改不能从父级传播到子级(例如,使用 mergeChangesFromContextDidSaveNotification:)。我目前正在尝试重置:每当父级保存时,然后通知所有对子级感兴趣的视图重新获取和更新。在我看来,当来自其他线程的更改来自持久存储(或 mergeChangesFromContextDidSaveNotification:) 时,从父级到子级的传播是必要的。【参考方案2】:

“获取”是什么意思?获取的结果控制器?

从我的角度来看,您的问题的答案是一般的“是”。假设某种共享父上下文,两个上下文将获取最新的对象,如果一个上下文保存了一个修改过的对象,而另一个上下文做了一些事情来再次加载它,例如,使用 objectID 和 - objectWithID: 在另一个上下文,重新加载它。

【讨论】:

就“获取”而言,我的意思是使用 NSFetchRequest 对象再次查找获取对象。 NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"ManagedItem" inManagedObjectContext:context];

以上是关于在 Core Data 中执行子获取时,在父上下文中修改托管对象是不是会向下传播到子上下文?的主要内容,如果未能解决你的问题,请参考以下文章

Core Data 后台处理,保存不推送到主上下文

php多进程编程实现与优化

应用重新启动时数据不会在 Core Data 中持久化

查询Core Data中多个子实体类型的所有对象

使用 EF Core 保存附加实体时如何删除子实体

core data 获取本周数据