7

我在SO内进行了搜索,但是在处理关系时,我没有发现任何关于删除核心数据中的被管理对象的性能的建议。关于在核心数据中使用级联规则删除被管理对象的性能考虑

这个场景很简单。 enter image description here

正如你所看到的,有三种不同的实体。每个实体都与下一个级联链接。例如,FirstLevel具有secondLevelsSecondLevel的关系。从FirstLevelSecondLevel的删除规则是级联而从SecondLevelFirstLevel的删除规则是否定。在SecondLevelThirdLevel之间应用相同的规则。

当我想要删除整个图中,我执行一种方法如下所示:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FirstLevel" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

NSError *error = nil; 
NSArray *items = [context executeFetchRequest:fetchRequest error:&error]; 
[fetchRequest release];  

// delete roots object and let Core Data to do the rest... 
for (NSManagedObject *managedObject in items) { 
    [context deleteObject:managedObject]; 
} 

服用级联统治图形被去除的优点。这对于少数物体可以快速工作,但会降低许多物体的性能。另外,我认为(但我不太确定)这种类型的删除对磁盘执行了很多往返操作,我错了吗?

因此,我的问题如下:如何在不利用Cascade规则和提升性能的情况下删除图表,但同时保持图形一致性?

预先感谢您。

编辑

,因为我在我的模型中的其他实体,我不能删除整个文件。

编辑2

我发布的代码被包装在NSOperation子类的main方法。该解决方案允许删除阶段在后台执行。由于我利用了级联规则删除是以半自动方式执行的。我只通过发布的代码中的for循环删除根对象,即FirstLevel项。以这种方式核心数据为我做了其余的。我想知道的是:是否有可能通过半自动删除操作,并手动执行而不会失去图形一致性?

+0

做tou想删除整个图,我的意思是,清除所有的持久性存储,或只是一些分支? – 2012-04-17 08:57:50

+0

整个图。 – 2012-04-17 09:03:14

+1

Thenmaybe这会帮助你吗?http://stackoverflow.com/questions/3266084/how-to-remove-all-objects-from-core-data – 2012-04-17 09:15:53

回答

5

对于遍历和删除数据库中的对象所花费的时间你无能为力。但是,您可以在后台执行此操作,以避免UI被阻止。

例如,像(代码假设ARC - 和刚刚输入 - 不编译)...

- (void)deleteAllLevelsInMOC:(NSManagedObjectContext*)moc 
{ 
    // Create a context with a private queue, so access happens on a separate thread. 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    // Insert this context into the current context hierarchy 
    context.parentContext = context; 
    // Execute the block on the queue of the context 
    context.performBlock:^{ 
      NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"FirstLevel"]; 
      // This will not load any properties - just object id 
      fetchRequest.includesPropertyValues = NO; 
      // Iterate over all first-level objects, deleting each one 
      [[context executeFetchRequest:fetchRequest error:0] 
       enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
       [context deleteObject:obj]; 
      }]; 
      // Push the changes out of the context 
      [context save:0]; 
    }]; 
} 

注意,你可以一个根层次Rootlevel对象添加到您的数据模型,并给它一个与第一级对象的一对多关系。然后,(只要你只有一个根对象),你所要做的就是删除这个根对象,它将删除CoreData中的其他所有内容。如果你有很多FirstLevel对象,那就是要走的路。

或者,您可以将您的“新”上下文直接连接到持久性存储,进行更改,并让其他上下文监视更改通知。

顺便说一句,如果你正在使用UIManagedDocument,你得到这种backgrounding免费的,因为已经有它自己的队列运行父上下文,并在右键所有的改变都将传递给实际做父数据库工作。

编辑

你可以做手工,但你必须关闭级联规则。我发现我希望CoreData尽可能为我做很多事情。它减少了我的误差。

如果您已经在后台线程中删除,那么您如何看到性能问题?您在删除期间必须查询......这意味着您正在使用MOC来完成所有工作。

你应该从UIManagedDocument上一堂课。你应该有一个在私人队列上运行的MOC。它完成了所有的实际工作。你有一个孩子MOC只是将工作传递给该工作者队列。

如果您实际正在查询不在您要删除的图形中的对象,它们可能会被持久存储协调器的序列化属性挂起。如果是这样的话,你应该考虑一个单独的协调员,或者只有两个商店。

通过这种方式,您可以根据需要删除图形中的对象,同时仍能响应其他对象的请求。

+0

+1获得支持。我已经在后台线程中删除了。你能否更好地解释你的意思是什么?你可以直接将你的“新”上下文连接到持久存储,进行更改,并让其他上下文关注更改通知*?谢谢。 – 2012-04-19 17:15:30

+0

也许会发布完整的删除代码,然后......至于第二部分,您可以创建多个使用相同NSPersistentStoreCoordinator的MOC。但是,这将序列化对商店的访问...您也可以创建单独的NSPersistentStoreCoordinator,然后您将可以并行访问商店...但您还有其他问题需要处理。一般来说,最简单的解决方案总是最好的。 – 2012-04-19 17:30:11

+0

谢谢你的回复。创建多个MOC可能是一个有效的解决方案,但我需要一次完成删除操作。看到我的第二个编辑。再次感谢你。 – 2012-04-19 18:25:04

1

我通常打开核心数据SQL跟踪-com.apple.CoreData.SQLDebug 1如下所述:http://useyourloaf.com/blog/2010/3/11/debugging-core-data-on-the-iphone.html 这有助于检查核心数据做我希望它在幕后做。

您是否确定[moc save:...]需要那么长时间,而不是实际的fetchrequest来获取要删除的对象?如果是这种情况,您可以批量获取(然后删除)这些firstlevel对象。

相关问题