核心数据迁移后的NSRangeException

Dav*_*tti 5 core-data core-data-migration nsrangeexception

在我的应用程序中添加新的Core Data模型版本后,我执行了轻量级迁移,显然已成功完成.迁移的文件加载正常,但在第一次尝试通过特定关系访问属性时,应用程序崩溃了NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'.这种关系在迁移之前运行良好.我从其他帖子中了解到4294967295确实存在-1,但我唯一可以识别出我的应用程序/数据中有36个项目的是数据模型中共有36个实体(供参考,正在获取的关系有58个项目)它的表).

问题:

我的问题是:基于我得到的错误以及我在下面进行的故障排除,是否存在一种可以通过轻量级迁移的模式更改,但是在此过程中损坏了数据,导致了注意到的异常?我将尝试将迁移分解为几个版本的较小块,以隔离或避免问题,但能够专注于可能有问题的特定架构更改会很好.

失败:

使用"myobject"中的以下代码发生故障:

[[self object2] text];
Run Code Online (Sandbox Code Playgroud)

object2关系是一对一,非可选的两种方式,并且数据模型之间的正向和反向关系都没有改变.该text属性可能不相关,因为在发生错误时,awakeFromFetch在object2中未达到该属性.如果我[self object2]在上述语句之前分配变量,则分配成功并报告data: <fault>.

数据库:

在sqlite3中查看数据库,我注意到以下内容:

  1. 前向和反向关系的索引值在每个表中看起来都是正确的.
  2. object2表有两列用于反向关系,而不是迁移之前的那一列(ZMYOBJECT如前所述,另外一列Z2_MYOBJECT,对于所有行都是空的).没有添加任何其他关系来解释此专栏.
  3. Z_PRIMARYKEY表中,迁移后的所有条目都显示-1Z_MAX,而在迁移之前,它们对于空表和零填充表的最大行数显示为零.手动更新Z_MAX到正确的值对例外没有帮助.所有Z_SUPER数值都是正确的.

我设置了一个映射模型,看看自动映射是否有任何错误,但一切看起来都很好.

整体架构更改:

在数据模型的源版本中,有14个实体,其中只有4个已经填充了数据(应用程序仍处于开发阶段).七个是顶级实体,七个是三个顶级实体的子实体.

在数据模型的目标版本中,添加了22个实体,一些顶级实体和一些子实体,具有几十个关系,包括一些添加到现有实体的关系.

某些属性和关系已从现有实体中删除,其他属性和关系已添加.未更改任何数据类型或关系设置,未重命名任何属性或关系,也不需要特殊映射.

更新(2/25/12):当我开始研究一个新的中间模型时,我记得我已经将NSManagedObject中的许多实体的类(representClassName)更改为NSManagedObject子类,但是没有生成类文件.我没有怀疑会导致问题,实际上,创建所有类文件对例外没有帮助.我只想注意到模型之间的另一个变化.

结论:

这是一个疯狂的猜测,但如果36实体计数不是巧合,似乎当"myobject"尝试在"object2"中出错时,它没有表的有效引用并且正在尝试加载表号-1 ,导致异常.[self object2]然而,简单分配成功的事实并不符合这一结论.

有任何想法吗?

Dav*_*tti 2

通过几次增量迁移,我能够确定导致问题的原因以及解决方案。

问题:

具有数据的现有实体之一在当前模型中没有子实体。如果我创建一个新模型,仅添加一个子实体,不包含任何属性或关系,并且不进行其他更改,则 NSRangeException、Z_MAX 观察以及我的问题中提到的逆关系加倍都会发生。

解决方案:

在观察上述案例的“成功”轻量级迁移后的失败之后,我创建了一个映射模型。由于唯一的变化是增加了一个实体,因此除一个之外的所有实体映射都很简单。问题是如何处理单个添加的实体。

默认情况下,添加的实体本身没有属性或关系,会显示所有父级属性的属性和关系映射。默认情况下,所有映射都有空值表达式,我认为这意味着它会在迁移过程中跳过它们。显然,这不是真的。通过删除实体映射中的所有属性和关系映射,然后关闭推断映射,迁移成功进行。

我仍然需要处理所有剩余的实体,并将尝试这种方法来批量完成其余的工作,并保持所有计划的属性和关系完好无损。