应用升级后核心数据关系丢失
Posted
技术标签:
【中文标题】应用升级后核心数据关系丢失【英文标题】:Core Data Relationship Lost After App Upgrade 【发布时间】:2011-09-13 05:26:09 【问题描述】:我有一个棘手的问题,我找不到答案。我的数据模型结构如下:
版本 1: 项目有很多地点 位置有很多项目 但是由于错误地从未设置过两者之间的倒数。
版本 2: 与上面相同,但现在设置相反。
我的问题的一个例子如下: 在版本 1 中,我有两个拥有相同位置的项目。当我启动第 2 版并处理我的映射模型时,拥有该位置的原始项目失去了与该位置的关系,现在该位置仅显示为其中一个项目的一部分,而不是两个项目的一部分。
我知道这个问题很可能是由于我没有设置项目和位置之间的反向关系,但是我可以做些什么来使数据在应用程序/数据模型的两个版本中持久存在?
编辑:
我尝试过推断映射模型,并尝试手动创建映射模型。我目前只在创建NSPersistentStoreCoordinator
时使用NSMigratePersistentStoresAutomaticallyOption
键。
另外,为了清楚起见,我有两个版本的数据模型并且迁移成功发生,唯一的问题是关系没有按预期持续。
编辑 2: 我发现我需要继承 NSEntityMigrationPolicy。我不想进行完全自定义的迁移,如果可能的话,我宁愿让我的其余迁移保持自动。有谁知道与我的目的相关的关于子类化 NSEntityMigrationPolicy 的任何好的教程或示例?我找不到太多,据我所知,Apples 文档中很少提及它。
编辑 3: 我一生都无法弄清楚如何使用 NSEntityMigrationPolicy 建立反向关系。我的问题现在与我之前描述的有点不同。有谁知道如何做到这一点的任何可靠的例子?
【问题讨论】:
"我的映射模型已处理" -> 将映射两个模型的代码放在这里。 【参考方案1】:倒霉。
您必须通过子类化 NSEntityMigrationPolicy 手动进行迁移:(
阅读documentation here - 特别是关于自定义实体迁移策略的部分。
作为迁移的一部分,您必须自己创建反向关系。
S
【讨论】:
是的,我今天早上早些时候在文档中读到了这一点,但实际上我还没有找到一个很好的例子来说明如何做到这一点。我不想手动迁移所有内容,我相信我可以迁移某些实体。【参考方案2】:使用自动迁移模型设置您的持久存储协调器,看看是否可行。另外,您确实创建了一个新模型版本,对吗?如果没有两个模型,Core Data 就无法映射。
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
// Handle error
【讨论】:
是的,我设置了一个新的模型版本。升级成功但关系丢失。我将尝试自动迁移,谢谢您的提示。 推断的映射模型不走运,它与我手动创建的映射模型具有相同的结果(这是有道理的 - 推断的映射模型似乎只是蛮力地强制您捆绑中的不同模型直到找到合适的一对)。【参考方案3】:您的第二个模型是否意外将关系从“一对多”更改?
如果是这样,您的迁移可能只会将一个位置分配给一个项目,因为它会从旧模型转换为新模型。
(这是猜测!)
【讨论】:
【参考方案4】:对于遇到这种情况的其他人,实际上有一个我没有考虑过的非常简单的答案。
我在尝试继承 NSEntityMigrationPolicy
方面并没有走得太远——我找不到任何超出基础的好的示例代码。在某些情况下,子类化NSEntityMigrationPolicy
可能是最好的解决方案。但是如果你和我处于同样的情况——(意味着你已经在你的模型中为逆关系设置了正确的字段,但你忘了实际指定逆),我相信我有一个更简单的解决方案。
我没有继承 NSEntityMigrationPolicy
,而是执行了以下操作(这实际上是更简单的 IMO):
(请记住,我的模型设置如下:Projects Locations,has-and-belongs-to-many 关系)
我将旧数据模型 (.xcdatamodel) 文件保留在我的应用程序中。当我的应用首次加载时,它会从旧数据模型文件中加载我的NSManagedObjectModel
。然后我继续遍历我的数据库中的所有项目,遍历每个项目的所有位置,并且对于每个位置,我将手动设置“项目”字段——如果我第一次设置我的模型是正确的,这将使用反向关系自动完成。这是我的代码的样子:
NSArray *projects = [context executeFetchRequest:request error:&error];
for(Project *project in projects)
for(Location *location in project.locations)
// set the inverse relationship manually
[location addProjectsObject:project];
我保存了我的NSManagedObjectContext
。
然后我摆脱了我的 NSManagedObjectContext
、NSManagedObjectModel
、NSPersistentStoreCoordinator
并使用我的新 xcdatamodel 文件重建它们。新模型文件包含反比关系,并且它们设置正确。从 SQLite 数据库迁移数据时,所有数据都保留了下来,并且我手动设置的反向关系仍然存在。创建新的NSPersistentStoreCoordinator
时,请务必指定NSMigratePersistentStoresAutomaticallyOption
选项。
【讨论】:
以上是关于应用升级后核心数据关系丢失的主要内容,如果未能解决你的问题,请参考以下文章
核心数据(添加唯一约束后):注释:修复丢失的删除传播以实现对多关系