核心数据故障和多对多关系的获取

发布于 2025-01-05 23:26:41 字数 3031 浏览 3 评论 0原文

我对核心数据行为有几个“理论”问题,这些问题涉及到多对关系会发生什么、何时依赖从父实体遍历关系以及何时应构建新的获取请求。它们都非常相关。

背景

假设有一个父实体RPBook,它与RPChapter 具有一对多关系。一本书有很多章节。核心数据模型中也设置了逆矩阵。涉及手动排序关系的基本形式,因此 RPChapter 实体具有 chapterIndex 属性。我在这里没有使用 iOS5 新的有序关系(也与这些问题无关)。

要访问书中的章节,可以使用 chapters 关系访问器:

RPBook *myBook; // Assume this is already set to an existing RPBook
NSSet *myChapters = myBook.chapters

使用/设置

在 iPhone 应用程序中,我们从显示 RPBook< 列表的表格视图开始/code> 实例。相应的章节不会作为支持表视图的获取结果控制器的获取规范的一部分进行预获取,因为还不需要这些章节。

我现在选择其中一个 RPBook 实例,我被带到一个新页面,并且我的视图控制器中有这个 RPBook 实例引用,它没有它的 章节 已预取。

问题 1:立即在 chapters 关系上调用 filteredSetUsingPredicate:

如果我想使用 filteredSetUsingPredicate: 通过 chapters 关系进行过滤> 直接,考虑到我没有预取我正在查看的当前 RPBook 的所有相关 RPChapter 实例,这是否可以可靠地工作?换句话说,filteredSetUsingPredicate:是否会在该关系中的所有对象的幕后触发故障以完成其任务,或者它是否会误导性地仅根据已经发生的章节给出结果在内存中(如果有的话)?

如果我没有大量与一本书相关的章节,我是否应该首先通过调用 allObjects 来设置样式?即

[[self.chapters allObjects] filteredArrayUsingPredicate:predicate]

而不是仅仅:

[self.chapters filteredSetUsingPredicate:predicate]

问题2:批量检索一本书的所有章节

如果我有一个RPBook实例,但没有预取与其相关的RPChapter实例,如何我是否强制使用 chapters 关系一次获取一本书的所有章节? [myBook.chapters allObjects] 是否会这样做,或者我仍然可以从该调用中返回错误吗?

我希望 Core Data 能够批量解决所有错误,而不是为奇怪的 RPChapter 询问是否会影响在 上使用 filteredSetUsingPredicate: 的行为而触发错误>chapters 关系,如上面的问题 1 所示。

我必须诉诸显式获取请求才能执行此操作吗?我是否应该重新获取已有的 RPBook,但这一次,在获取请求中请求所有关联的章节也使用 setRelationshipKeyPathsForPrefetching: 获取?

最后一个选项对我来说似乎很浪费,因为我已经有了一个范围关系,它在概念上代表了我感兴趣的所有 RPChapter 实例的子集。我会尽可能地”我只想遍历对象图。

问题 3:同一线程上 RPChapter 实例的 NSFetchedResultsController

Setup 在本例中,我有一个 RPBook 实例,但没有与其相关的预取 RPChapter 实例(但它们确实存在于 Store 中)。在同一个视图控制器中,我还有一个 NSFetchedResultsController (FRC),其范围为同一本书的 RPChapter 实例。所以这是相同的线程,相同的托管对象上下文。

FRC 中的 RPChapter 实例与我从 myBook.chapters 中检索的 RPChapter 实例对应的内存中的对象是否相同?相同的ObjectID?换句话说,运行时是否曾经使用不同物理对象来满足同一线程中同一MOC对相同ObjectID的托管对象请求在记忆中?

问题 4:在托管对象内安装 NSFetchedResultsController 来为关系查询提供服务的设计模式

我正在尝试决定是否应该能够为内容经常更改的关系的查询提供服务(章节在我的示例中的一本书中)通过使用我的自定义 RPChapter 托管对象子类中提供的内置 chapters 关系,或者如果从设计/架构的角度来看可以的话,安装RPChapter 实例的 FRCRPBook 托管对象类上,以有效地服务有关该书中章节的查询。

如果我可以只依赖 myBook 实例中的 chapters 访问器,那么显然会更干净,但在大量数据的情况下,这里的 FRC 实际上可能会更高效、更高效。存在对多关系中的目标实体。

这是过度杀伤还是这是合理使用 FRC 来以不同方式查询 RPBook 的章节?不知怎的,感觉我错过了简单地遍历对象图的机会。我希望能够相信,当我加载 RPBook 实例时,chapters 关系始终是最新的。

I have several "theory" questions on Core Data behavior related to what happens with a to-many relationship and when to rely on walking the relation from a parent entity and when a fresh fetch request should be built. They're all very much related.

Background

Assume a parent entity RPBook, which has a to-many relation to RPChapter. A book has many chapters. The inverse is set in the core data model too. A basic form of manually ordered relationships is involved, so the RPChapter entity has a chapterIndex property. I am not using iOS5's new ordered relationships here (not as relevant to these questions either).

To get to the chapters in a book, one would use the chapters relationship accessor:

RPBook *myBook; // Assume this is already set to an existing RPBook
NSSet *myChapters = myBook.chapters

Usage / Setup

In an iPhone app, we'd start off with a table view showing a list of RPBook instances. The corresponding chapters wouldn't be pre-fetched as part of the fetch spec for the fetched results controller backing the table view, since those chapters are not yet needed.

I now select one of those RPBook instances, I'm taken to a new page and I have this RPBook instance reference in my view controller, which does NOT have its chapters prefetched.

Question 1: Invoking filteredSetUsingPredicate: on chapters relation right away

If I want to filter via the chapters relation using filteredSetUsingPredicate: directly, will that even work reliably, given that I didn't pre-fetch all related RPChapter instances of the current RPBook I'm looking at? Put another way, does filteredSetUsingPredicate: trigger faulting behind the scenes of all objects in that relation in order to do its thing, or will it misleadingly only give me results based on which of the chapters already happened to be in memory (if any)?

If I don't have an egregious number of associated chapters to a book, should I instead style this by invoking allObjects first? i.e.

[[self.chapters allObjects] filteredArrayUsingPredicate:predicate]

instead of just:

[self.chapters filteredSetUsingPredicate:predicate]

Question 2: Batch retrieval of all a book's chapters

In the case I have an RPBook instance, but no pre-fetched RPChapter instances related to it, how do I force all of a book's chapters to be fetched in one shot using the chapters relation? Does [myBook.chapters allObjects] do that or can I still get faults back from that call?

I want Core Data to fulfill all the faults in a batch instead of tripping faults for the odd RPChapter asked for if that will affect the behavior of using filteredSetUsingPredicate: on the chapters relation, as per Question 1 above.

Must I resort to an explicit fetch request to do this? Should I refetch the RPBook I already have, but this time, request in the fetch request, that all associated chapters also be fetched using setRelationshipKeyPathsForPrefetching:?

This last option just seems wasteful to me, b/c I already have a scope relation representing conceptually the subset of all RPChapter instances I'd be interested in. As much as possible, I'd like to just walk the object graph.

Question 3: NSFetchedResultsController of RPChapter instances on the same Thread

Setup
In this case I have an RPBook instance, but no pre-fetched RPChapter instances related to it (but they do exist in the Store). In the same view controller, I also have an NSFetchedResultsController (FRC) of RPChapter instances scoped to the very same book. So that's same thread, same managed object context.

Is an RPChapter instance from the FRC going to be the same object in memory as an RPChapter instance counterpart I retrieve from myBook.chapters, that shares the same ObjectID? Put another way, does the runtime ever fulfill managed object requests for the same ObjectID from the same MOC in the same Thread, using different physical objects in memory?

Question 4: Design pattern of installing an NSFetchedResultsController inside a Managed Object to serve queries for a relation

I'm trying to decide whether I should be able to service queries about a relationship whose contents are frequently changing (chapters in a book in my example) by using the built in chapters relation provided in my custom RPChapter managed object subclass, or if it's ever okay from a design/architecture perspective, to install an FRC of RPChapter instances onto the RPBook managed object class, to service queries efficiently about chapters in that book.

It's clearly cleaner if I could just rely on the chapters accessor in myBook instance, but it seems an FRC here might actually be more performant and efficient in situations where a large volume of destination entities in the to-many relation exist.

Is this overkill or is this a fair use of an FRC for querying an RPBook about its chapters in different ways? Somehow it feels like I'm missing the opportunity to walk the object graph simply. I'd like to be able to trust that the chapters relation is always up to date when I load my RPBook instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

嘿看小鸭子会跑 2025-01-12 23:26:41

问题 1

是的,它会起作用。当您调用[book Chapters]时,该集合将自动填充。当您过滤这些对象时,它们会出错。

但是,您应该在此处使用 NSFetchedResultsController ,其谓词类似于@“book == %@”,而不是抓取数组。

问题 2

强制 NSManagedObjectContext 加载所有章节的最佳方法是执行 NSFetchRequest 并配置 NSFetchRequest 返回完全实现的内容对象而不是错误。这将一次性将它们全部预加载。然而,除非你有大量的章节,否则你不会在这里节省很多。

为什么?

因为当您请求这些章节时,即使在故障状态下,Core Data 也会将数据加载到缓存中(不包括二进制数据等一些边缘情况),这样当您“故障”一个对象时,它只是在其中移动的指针内存并且没有额外的磁盘命中。

您可能需要阅读数千章才能看到预取的好处。

问题3

是的。它们将是同一个对象。从同一个 NSManagedObjectContext 检索时,NSManagedObject 实例将始终被共享。这是 NSManagedObjectContext 工作的一部分。

问题 4

您想要使用 NSFetchedResultsControler 这就是它的工作。手动管理这些东西是浪费的,而且几乎肯定比 Core Data 的实现效率低。

但是,关系将始终是最新的,除非您从另一个线程对其进行调整。因此,如果您不期望更新,那么您可以只使用数组。我不会。

Question 1

Yes it will work. When you call [book chapters] the set will get populated automatically. When you filter on those objects they will fault in.

However, you should be using a NSFetchedResultsController here with the predicate being something like @"book == %@" instead of grabbing the array.

Question 2

The best way to force the NSManagedObjectContext to load all of the chapters would be to do a NSFetchRequest and configure the NSFetchRequest to return fully realized objects instead of faults. This will pre-load them all in one go. However, unless you have a TON of chapters, you are not going to get a lot of savings here.

Why?

Because when you request those chapters, even in a faulted state, Core Data is going to load the data into a cache (excluding a few edge cases like binary data) so that when you "fault" an object it is just pointers moving around in memory and no additional disk hit.

You would need, probably, thousands of chapters to see any benefit out of a pre-fetch.

Question 3

Yes. They will be the same object. NSManagedObject instances will always be shared when retrieved from the same NSManagedObjectContext. That is part of the job of the NSManagedObjectContext

Question 4

You want to use a NSFetchedResultsControler that is its job. Managing that stuff manually is wasteful and almost guaranteed to be less efficient than Core Data's implementation.

However, the relationship will always be up to date unless you are tweaking it from another thread. So if you do not expect updates then you could just use an array. I wouldn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文