具有唯一约束的多线程coredata用于upsert

时间:2017-02-06 09:55:58

标签: ios objective-c multithreading core-data managedobjectcontext

大家好我正在开发一个使用coredata(多线程)的应用程序,下面是使用的coredata堆栈(这是通过这里的教程设计的:https://www.cocoanetics.com/2012/07/multi-context-coredata/

模特

- (NSManagedObjectModel *)managedObjectModel {
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"XXX" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

主要背景

- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self writerManagedObjectContext];

    return _managedObjectContext;
}

作家背景

- (NSManagedObjectContext *)writerManagedObjectContext{
    if (_writerManagedObjectContext != nil) {
        return _writerManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _writerManagedObjectContext;
}

持久的商店评论

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator         = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSURL *storeURL                     = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"XXX.sqlite"];

    NSError *error = nil;
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"XXX" URL:storeURL options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

如您所见,WRITER上下文是MAIN上下文的父级,这意味着WRITER将处理将数据保存到存储,同时它还更新任何更改的MAIN上下文(在内存中)。

注意:WRITER保存到商店,因为POS已设置为WRITER上下文。

在模型中的实体上,我将'Id'设置为数据库中用于UPSERT的所有实体(表)的唯一约束(即等同于SQL insert OR replace)。

MAIN和WRITER上下文都将其合并策略设置为NSMergeByPropertyObjectTrumpMergePolicy,以确保WRITER,MAIN和商店之间的对象同步。

[[CoreDataCommons mainContext] setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[[CoreDataCommons writerContext] setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

现在,当我想插入数据库时​​,我创建了一个新的上下文:

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:writerManagedObjectContext];

[context performBlock:^{

   // Populate entity attributes and save
   for (id object in objects){


      // Save every 500 objects
      if (count % 500 == 0){
         if ([context save:&error]){
        }
      }
      count++;
   }

   // Final save if anything unsaved
   if ([context save:&error]){
   }

   // Save WRITER context which will push changes to MAIN context
    [writerManagedObjectContext performBlock:^{
        if (![writerManagedObjectContext save:&writerError]) {
            DLog(@"Writer: Unresolved error %@, %@", writerError, [writerError localizedDescription]);
    }]; 
}]; 

问题

当第一次加载应用程序时,它会从API加载大约15000个对象(类型JSON),它会在大约3秒内写入这些数据(我认为这有点太长但不是主要问题);但第一次加载不是问题。 ISSUE来自API的后续加载;因此,第二次加载它需要大约5分钟来写相同的数据,它也会阻止主线。

经过一些调试后,我发现当数据库中已存在数据时,约束(即UPSERT)会导致保存时间过长。这意味着它还做了它的原始性

IF (EXIST){ // UPDATE}ELSE{ // INSERT}

我已经使用了多个上下文来确保不是这种情况,但它似乎仍然保留了主线程并且需要花费大量时间来保存。

问题 首先,是否会出现coredata堆栈引起的任何问题(即死锁,后台进程等)?

其次:是否需要用coredata保存对象的正常时间?如果没有,任何人都可以提出优化策略。

第三,我正在考虑绕过coredata并直接使用sqlite。有任何预见的障碍吗?除了coredata提供的安全层。

欢迎任何想法。

提前致谢。

0 个答案:

没有答案