3

想象一下CoreData中的以下关系

Recipe < --- >> Ingredient

我正在使用 MagicalRecord 定期将服务器数据库 (JSON API) 与我的本地 CoreData 数据库一起导入。

Recipe 1所以,如果我这样导入Ingredient 1

{
  id:1,
  name: "Recipe 1",
  ingredients: [{
    name: 'Ingredient 1'
  }]
}

所以非常好,MagicalRecord 创建了两个实体并将它们链接在一起。

当服务器更改为以下内容时出现问题:

{
  id:1,
  name: "Recipe 1",
  ingredients: [{
    name: 'Ingredient 2' <-- Notice here
  }]
}

MagicalRecord 所做的是创建Ingredient 2记录(正确),将其链接为(正确)的唯一成分Recipe 1。但是,如果我搜索成分,我会在我的 CoreData 数据库中找到2条记录。

所以问题是,是否可以在导入和删除对象时跟踪“已删除”对象?

4

3 回答 3

1

我按照这个过程解决了这个问题。

  1. 在您的核心数据存储上运行一个查询,该查询将返回您对任何给定服务器请求的期望值。查找预期由服务器返回的查询找到的每个对象的所有 objectID。
  2. 发出服务器请求并导入数据。
  3. 在保存之前,从您刚刚用于导入数据的上下文中获取所有更新的对象。
  4. 删除原始 objectID 列表中不在更新后 objectID 列表中的任何对象

这种方法应该为任何给定的请求实现所需的行为。请注意,您仍然可能会删除从其他地方引用的记录,因此只有在将来的其他请求可以重新创建它们时才使用这种方法。

导入代码

NSArray *existingObjectIDs = [self existingObjectIDsForYourQuery];

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
                    [Recipe MR_importFromObject:response inContext:localContext];
                    NSArray *objectIDs = [[[localContext updatedObjects] allObjects] valueForKey:@"objectID"];
                    [self deleteLocalObjectsWithObjectIDs:existingObjectIDs excludingImportedObjectIDs:objectIDs];
}];

删除代码

- (void)deleteLocalObjectsWithObjectIDs:(NSArray *)existingObjectIDs excludingImportedObjectIDs:(NSArray *)importedObjectIDs {
    NSMutableArray *objectsToDelete = [NSMutableArray arrayWithArray:existingObjectIDs];

    for ( NSManagedObjectID *objectID in importedObjectIDs ) {
        [objectsToDelete removeObject:objectID];
    }

    [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
        for ( NSManagedObjectID *objectID in objectsToDelete ) {
            NSManagedObject *object = [localContext existingObjectWithID:objectID error:nil];

            if ( object ) {
                [localContext deleteObject:object];
            }
        }
    }];
}
于 2014-05-14T02:38:36.237 回答
1

这里真正的问题是 MagicalRecord 似乎正在导入重复项。这个问题应该已经在最近的更新中解决了,但是,如果你仍然有问题,我建议在项目问题页面上打开一张票

于 2012-07-23T14:15:39.183 回答
0

Ingredient如果这是您用作主键的名称,则不能只更改服务器上的名称。MagicalRecord 和 Core Data 不知道更新了哪条记录,它只知道不Ingredient存在具有该名称的记录,它会为您创建一个新记录并从Recipe. 您必须手动删除本地应用程序数据库中 JSON 有效负载中不存在的所有记录。

考虑以下:

您的Ingredient对象没有主键。您必须让 MagicalRecord 知道哪个键是主键(当不存在“ingredientID”属性时。

您可以通过进入核心数据模型并选择Ingredient实体来完成此操作。接下来,在数据模型检查器的用户信息中添加一个“relatedByAttribute”键,值是“name”。

接下来进入您的Recipe实体,选择关系Ingredient并在用户字典中为关系添加“relatedByAttribute”键和“name”值。这样,MagicalRecord 现在知道Ingredient通过“名称”属性查找任何现有记录,如果存在,它将映射到现有记录,其他记录创建一个新实体并链接Recipe到它。

您可以在此处阅读更多信息:http ://www.cimgf.com/2012/05/29/importing-data-made-easy/ ,特别是您感兴趣的“按键相关”部分。

同样,如上所述,您只更新了名称,这意味着您可能应该删除Ingredient当前Recipe. 如果您删除服务器上的对象,您也需要在本地数据库中删除它。

如果您仍然遇到问题,我建议您创建一个类别类Recipe,您可以在其中手动查找与名称匹配的任何记录并相应地创建/更新。但是不要忘记删除payload中不存在但本地存在的记录。

于 2013-02-09T14:47:57.580 回答