将数据插入核心数据时的奇怪行为

Posted

技术标签:

【中文标题】将数据插入核心数据时的奇怪行为【英文标题】:Strange behaviour when inserting data into core-data 【发布时间】:2014-08-19 17:58:23 【问题描述】:

编辑 1 虽然我知道对于这种特殊情况(和其他类似情况),我可以单独使用映射编辑器来正确迁移我的存储,以便持久存储中的值不会跳来跳去,但这不是我当前问题的解决方案,而只是避免解决问题的根源。我热衷于坚持我的自定义迁移策略,因为这将使我在迁移过程中获得很多控制权,特别是对于未来设置自定义迁移策略对我有用的场景。这是一个长期的解决方案,而不仅仅是针对这种情况。

我敦促您尝试帮助我解决当前的情况,而不是让我转向轻量级迁移或建议我避免使用迁移策略。谢谢。

我真的很期待解决这个问题以及您对我可以做些什么来解决这个问题的宝贵意见/想法。

我做了什么: 我设置了迁移策略,以便可以将源数据从核心模型的version 1 复制到新的目标数据到version 2

这是迁移政策:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error 

    // Create the product managed object
    Product *newProductInstance = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
                                                                inManagedObjectContext:[manager destinationContext]];

    NSString *productCode = [sInstance valueForKey:@"productCode"];
    NSNumber *productPrice = [sInstance valueForKey:@"productPrice"];
    [newProductInstance setProductCode: productCode];
    [newProductInstance setProductPrice:productPrice];

    /**
     The previous old product entries didnt have anything for the last attribute,
     where as the new instances of product entity should have a default value of YES.
     */
    [newProductInstance setProductPriceNeedsUpdating:[NSNumber numberWithBool:YES]];

    /*
    A test statement to make sure the destination object contains the correct
    values int he right properties:

    Product description: <NSManagedObject: 0xb983780> (entity: Product; id: 0xb9837b0 <x-coredata:///Product/t97685A9D-09B4-475F-BDE3-BC9176454AEF6> ; data: 
        productCode = 9999;
        productPrice = "2.09";
        productPriceNeedsUpdating = 1;
    )
    */
    NSLog(@"Product description: %@", [newProductInstance description]);

    // Set up the association between the old source product and the new destination Product for the migration manager
    [manager associateSourceInstance:sInstance
             withDestinationInstance:newProductInstance
                    forEntityMapping:mapping];
    return YES;

因此,即使测试的属性在运行时显示正确的值,保存在数据模型存储中的结果值也不正确,如快照所示。

这是数据存储版本 1 与版本 2 的比较。

版本 1:正确

到版本 2:现在错误地存储了值。

预期的输出应该将 Product price 插入到 productPrice 字段中,而不是在实际上应该只有布尔值的 ProductPriceNeedsUpdating 字段中。 谁能帮我理解我做错了什么,或者解释一下这里发生了什么?

更新 1 - 这是我的entity mappings

更新 2 - 2014 年 8 月 20 日 01:02 GMT

当我从版本 1 中删除 date 类型的属性 ProductPriceLastUpdated,并在版本 2 中删除 boolean 类型的属性 ProductPriceNeedsUpdate 时,只留下在版本 1 和 2 中都匹配的两个属性,然后一切正常。即使我可以把它留在这里继续前进,我也不能忽略当前正在使用数据库版本 1 的用户,这些用户确实具有无意义的 ProductPriceLastUpdated 属性,我需要将类型转换为布尔值并且名称也更改为 @ 987654339@。那是事情开始变得奇怪的时候,价格值显示在ProductPriceNeedsUpdate 字段而不是productPrice 字段中。

我希望有人能解决最初的问题并告诉我为什么实体映射,或者更多,属性映射没有被正确保存?

更新 3 - EntityMapping 和属性:

版本 1

第 2 版

【问题讨论】:

您是否有特定的理由不进行轻量级迁移?如果您只是添加一个默认始终设置为 YES 的新字段,并删除另一个字段,Core Data 可以自行处理,无需进行自定义迁移。 @jcaron,我正在此应用程序上构建,最终将需要大量迁移,默认情况下没有设置为 yes,这只是一个练习,我将继续增加字段、关系和可能甚至分支实体,将它们分成两部分,最终……我可以继续。关键是,我有一个像魅力一样工作的自定义重迁移,一种渐进式迁移,它可以通过递归我拥有的方法从版本 1 迁移到版本 6,该方法继续升级商店模型,直到它与现有模型匹配。续。 @jcaron,我的问题是关于为什么将数据插入到不同的字段中。请尝试通过讨论其他形式的迁移来避免跑题,除非这对为什么我的数据在字段之间跳跃有直接相关的影响;) :P 另外,更改字段的属性不是轻量级迁移所涵盖的内容。看看这个帖子。 ***.com/questions/17534859/… @jcaron,感谢您抽出宝贵时间发表评论。您能想到什么可能会导致这个问题吗? 请注意,问题出在这部分代码中。我认为 NSLog 的注释输出是实际输出?你查过cases.azoft.com/database-migration-ios-applications的线索了吗? 【参考方案1】:

对于您的方案,不需要迁移策略。您可以只使用 映射模型 并执行以下操作:

    将不变的实体相互映射。在映射模型编辑器中,它应该显示类似A productCode | $source.productCode 的内容。这已经为您填写好了。 要删除的属性 (productPriceLastUpdated) 根本不应该出现,因为在创建映射模型时指定了源模型和目标模型。由于目标模型不包含此属性,因此不会显示。 在显示新布尔属性productPriceNeedsUpdating 的地方,为“值表达式”输入“1”(这相当于@YES)。它应该看起来像这样:A productPriceNeedsUpdating | 1

您现在无需定义策略,只需调用

migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:
destinationType:destinationOptions:error

您只需使用映射模型编辑器即可完成非常复杂的操作。

您的屏幕截图来自模型编辑器。确保您熟悉映射编辑器

【讨论】:

您好,感谢您的发帖。我有一个问题,是否有任何理由无法使用自定义迁移策略实现结果?我想用当前的设置解决这个问题,否则手头的问题没有得到解决,而只是被跳过了。我们能弄清楚为什么会出现我遇到的问题吗?我很高兴重新制定自定义迁移政策。 请记住,这只是我为以后更大的事情设置的一个小场景,最终会有一个场景以及更多自定义迁移策略更适合我自己的场景。我正在寻找一个长期的解决方案,而不是只适用于“这种情况”并且与之类似的解决方案。 我快速编写了一个包含自定义迁移的示例项目,它运行良好。我建议您逐行浏览策略代码,看看是否所有内容都具有您期望的值。您的映射模型看起来不错,但缺少布尔值 1。确保从模拟器中完全删除应用程序,设置以前的版本,运行它,创建一些数据,杀死它,切换到迁移版本,然后单步执行代码。 了解 Product 的子类在每个版本中都会发生变化,并且版本 3 的最新版本与版本 2 不同,是否有帮助?但我认为 Product 的子类(与版本 3 的属性匹配)与此无关。 可能。我的版本不使用任何托管对象子类。您没有将子类最佳实践 (setProperty) 与托管对象 KVC (setValue:forKey:) 混合在一起。

以上是关于将数据插入核心数据时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:使用延迟实例化时的奇怪错误行为

PDOStatement :: execute():SQLSTATE [HY093],批量插入时的奇怪行为

Oracle“插入”命令的奇怪行为

试图更新crud时的奇怪行为

尝试将行附加到按对象分组中的每个组时的奇怪行为

发送广播消息时的奇怪行为