1

没有完全解决这个问题的现有技术: 核心数据迁移错误消息“'模型不包含配置'XYZ'。'”

我已将其缩小到一个特定问题。不过,设置需要一分钟。请多多包涵。

问题的要点是persistentStoreCoordinator(显然)不能保留对象图的一部分,其中当托管对象存储在不同文件中时,它们被标记为另一个对象的子实体。开始...

1) 我有 2 个 xcdatamodel 文件,每个文件都包含一个实体。在运行时,当构建托管对象模型时,我使用 setSubentities: 手动将一个实体定义为另一个实体的子实体。这是因为尚不支持在编辑器中跨多个文件定义子实体。然后我用 modelByMergingModels 返回完整的模型。

//Works! 
[mainEntity setSubentities:canvasEntities];
NSLog(@"confirm %@ is super for %@", [[[canvasEntities lastObject] superentity] name], [[canvasEntities lastObject] name]);
//Output: "confirm Note is super for Browser"

2) 我修改了 persistentStoreCoordinator 方法,以便为每个实体设置不同的存储。从技术上讲,它使用配置,并且每个实体都定义了一个且只有一个配置。

//Also works!
for ( NSString *configName in [[HACanvasPluginManager shared].registeredCanvasTypes valueForKey:@"viewControllerClassName"] ) {
storeUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:[configName stringByAppendingPathExtension:@"sqlite"]]];
//NSLog(@"entities for configuration '%@': %@", configName, [[[self managedObjectModel] entitiesForConfiguration:configName] valueForKey:@"name"]);
//Output: "entities for configuration 'HATextCanvasController': (Note)"
//Output: "entities for configuration 'HAWebCanvasController': (Browser)"
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:configName URL:storeUrl options:options error:&error])
//etc

3)我为父实体设置了一个 fetchRequest,其中 setIncludesSubentities: 和 setAffectedStores: 只是为了确保我们同时涵盖了 1) 和 2)。当插入任一实体的对象时,它们都被添加到上下文中,并且它们都由 fetchedResultsController 获取并按预期显示在 tableView 中。

// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesSubentities:YES]; //NECESSARY to fetch all canvas types
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20]; // Set the batch size to a suitable number.
[fetchRequest setAffectedStores:[[managedObjectContext persistentStoreCoordinator] persistentStores]];
[fetchRequest setReturnsObjectsAsFaults:NO];

这是它开始行为不端的地方:关闭并重新启动应用程序后,仅获取父实体。

如果我使用 setEntity: 将请求的实体更改为“Note”的实体,则会获取所有注释。如果我将其更改为“浏览器”的实体,则会获取所有浏览器。让我重申一下,在对象首次插入上下文的运行期间,它将出现在列表中。只有在保存并重新启动后,获取请求才无法遍历层次结构。

因此,我只能得出结论,问题在于继承的存储。让我们回顾一下原因:

    - 两个实体都可以创建、插入到上下文中并查看,因此模型正在工作
    - 两个实体都可以通过一个请求获取,因此继承工作正常
    - 我可以确认文件正在单独存储,并且对象正在进入相应的存储区,因此正在保存
    - 使用为请求设置的任一实体启动应用程序都有效,因此从商店中检索工作正常
    - 这也意味着使用请求遍历不同的商店是有效的
    - 通过使用单个商店而不是多个商店,问题完全消失了,因此创建、存储、获取、查看等工作正常。

这只留下了一个罪魁祸首(在我看来):我使用 setSubentities 设置的继承:仅对会话期间创建的对象有效。

要么对象/实体被存储而没有继承信息,要么以编程方式定义的实体继承仅适用于新实例,或两者兼而有之。其中任何一个都是不可接受的。要么它是一个错误,要么我是方式,方式偏离路线。

我已经在这四处走动了两天;非常感谢任何见解。当前的解决方法 - 仅使用单个商店 - 完全有效,但如果我从应用程序中删除其中一个模型等,它不会是面向未来的。它也令人难以置信,因为我不明白为什么你如果核心定义(setSubentities:)不起作用,则将拥有所有这些基础架构,用于跨多个商店进行存储并在获取请求中设置受影响的商店。

4

2 回答 2

4

不幸的是,答案很简单。不支持跨物理不同的文件和/或模型的子实体。在底层数据结构中,Core Data 会将所有子实体扁平化为一个表。因此,如果您有一个 Parent、ChildA、ChildB 和 ChildC,每个都有 4 个属性,那么您最终将得到一个包含 16 列的表。

这就是您尝试的方式不支持子实体的原因。每个模型本身都是一个孤岛,最多只能对其他模型中的对象进行弱引用。

更新

正如我上面解释的那样,这是一个“不受设计支持”的问题。不支持您尝试执行的操作,因为它在底层数据结构中的持久化方式。创建子实体并不是您一开始就应该做的很多事情,因为它会扁平化您的数据模型。

实体继承等于对象继承。您的对象可以以您想要的任何方式、形状或形式继承。实体继承应该是非常罕见的,并且有一个很好的理由。

解决父子关系问题是使用实体继承的少数原因之一。

试图避免列的重复并不是一个好的理由。

由于您不能跨模型建立父/子关系(并且即使它们被合并到一个实例中,您也确实拥有多个模型NSManagedObjectModel),因此不太可能成为跨无法解决的模型进行实体继承的理由通过类似的解决方案。

于 2010-05-03T22:27:43.637 回答
0

@SG

你问:

为什么有所有这些钩子用于读取多个模型,并保存到多个持久存储......

您可以拥有多个模型并将它们保存到不同的持久存储中,因为您希望处理 xcdatamodel 的不同部分,例如编辑 EntityA 的属性影响与 EntityB 的关系,同时重新排序 EntityB 的大量 managedObjects。

您还可以在读取新对象时在另一个线程中执行更好的 I/O 流,完成这项工作后,您可以将它们与模型的现有数据“合并”。

于 2011-07-14T15:31:18.607 回答