两个上下文,1 个持久存储:重复获取的条目

Posted

技术标签:

【中文标题】两个上下文,1 个持久存储:重复获取的条目【英文标题】:Two Contexts, 1 Persistent Store: Duplicate Fetched Entries 【发布时间】:2011-09-07 06:08:40 【问题描述】:

我正在尝试为用户创建一种将联系人导入手机的方法。它的工作原理是这样的:

有两个托管对象上下文。 “真实”上下文在他们的地址簿中有当前数据。 “其他”上下文具有来自其他来源的传入数据。两者共享同一个 PersistentStoreCoordinator。

我通过电子邮件匹配人,所以如果“真实”上下文中的联系人匹配“其他”中的联系人,我不会保存另一个联系人。

当我启动程序时,我在“真实”上下文中有两个条目可以很好地获取。

然后,我导入另外两个联系人并将它们添加到“其他”上下文中。

当我对“其他”上下文执行提取操作时,我得到四个结果 - 两个来自“真实”上下文,两个我刚刚添加到“其他”上下文。

但是,当我合并更改时,我的重复检测方案有效。

我对 Core Data 的理解有什么遗漏吗?我怎样才能使我对“其他”上下文的查询只返回新结果。

完整的代码真的很长,但这里是重要的部分:

AppDelegate *appDel = (AppDelegate*)[[UIApplication sharedApplication] delegate];

// Check to see the original data
NSManagedObjectContext *realContext = [appDel managedObjectContext];
NSFetchRequest *usersFetch= [[[NSFetchRequest alloc] init] autorelease];
[usersFetch setEntity:[NSEntityDescription entityForName:@"User" inManagedObjectContext:realContext]];
[usersFetch setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"email" ascending:YES]]];

NSArray *users = [realContext executeFetchRequest:usersFetch error:&error];
[usersFetch release];
NSLog(@"%@",users);   // Returns 2 original objects already in database


otherContext = [[NSManagedObjectContext alloc] init];
[otherContext setPersistentStoreCoordinator:[[appDel managedObjectContext] persistentStoreCoordinator]];

for (contacts in fetchedData)
    User *newUser = (User*)[NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:otherContext];
    newUser.email = fetchedData.email;
    newUser.firstName = fetchedData.firstName;
    // etc.


NSFetchRequest *newUsersFetch = [[[NSFetchRequest alloc] init] autorelease];
[newUsersFetch setEntity:[NSEntityDescription entityForName:@"User" inManagedObjectContext:otherContext]];
[newUsersFetch setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"email" ascending:YES]]];
NSLog(@"%@",[otherContext registeredObjects]);   // 2 objects that were just added
NSArray *newUsers = [otherContext executeFetchRequest:newUsersFetch error:&error];
NSLog(@"%@",[otherContext registeredObjects]);  // 4 objects - added AND original
NSLog(@"Count: %i",[newUsers count]);                  // Count: 4

【问题讨论】:

【参考方案1】:

我认为您可能在概念上将托管对象上下文与持久存储混淆了。您可以将任意数量的上下文附加到特定商店,并且在任何单个上下文中所做的更改最终将显示在所有其他上下文中。

对于直接去商店查找对象的获取尤其如此。如果您在 other 上下文中调用 save,您的代码将按预期工作。保存对象后,它会进入持久存储并显示在所有实体范围的提取中。

您不应该创建可能有重复的托管对象。相反,通常的做法是获取新值以查看它们是否已经存在,并且仅在存储中不存在该值时才使用该值创建一个新的托管对象。为了加快速度,您可以获取特定属性并查看是否返回任何内容。

【讨论】:

知道了 - 所以只有当它们不在数据库中时才创建新对象。 “其他”上下文可用于增量创建记录,直到它们准备好保存 - 然后可以合并更改。 在同一个线程上使用两个或多个上下文很少会获得太多优势。由于这一切都发生在主线程上,您不妨只使用一个上下文,然后回滚或删除您决定不保存的任何对象。

以上是关于两个上下文,1 个持久存储:重复获取的条目的主要内容,如果未能解决你的问题,请参考以下文章

两个托管对象上下文可以共享一个持久存储协调器吗?

区分从内存中托管对象上下文和持久存储中获取的对象

无论当前上下文状态如何,如何获取 NSManagedObject 的持久存储副本

将对象从多个存储保存到单个持久存储

在哈希表的上下文中,“桶条目”是啥意思?

在核心数据的上下文之间共享非持久对象?