Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将大型数据集导入核心数据(具有多个存储的解决方案)_Ios_Json_Core Data_Import - Fatal编程技术网

Ios 将大型数据集导入核心数据(具有多个存储的解决方案)

Ios 将大型数据集导入核心数据(具有多个存储的解决方案),ios,json,core-data,import,Ios,Json,Core Data,Import,我知道这个主题已经讨论过了,但我正在寻找一个在任何地方都讨论过的特定解决方案,即使用多个存储而不是一个存储——一个存储默认数据,另一个存储用户输入的数据 在我的应用程序中,我希望为实体X(仅限)预加载大量数据,即20 MB json文件。该模型还包含实体Y和实体Z。我认为最适合我需要的解决方案如下: 使用两个sqlite数据库。仅实体X的一个数据库,可在应用程序的未来版本中替换。。。不影响实体Y和实体Z的数据(毫不费力) 我如何实现这样的解决方案 它实用吗 我要做两个模型吗 在这种情况下,我将

我知道这个主题已经讨论过了,但我正在寻找一个在任何地方都讨论过的特定解决方案,即使用多个存储而不是一个存储——一个存储默认数据,另一个存储用户输入的数据

在我的应用程序中,我希望为实体X(仅限)预加载大量数据,即20 MB json文件。该模型还包含实体Y和实体Z。我认为最适合我需要的解决方案如下:

使用两个sqlite数据库。仅实体X的一个数据库,可在应用程序的未来版本中替换。。。不影响实体Y和实体Z的数据(毫不费力)

  • 我如何实现这样的解决方案
  • 它实用吗
  • 我要做两个模型吗
  • 在这种情况下,我将如何设置核心数据管理对象上下文
细节(以防万一):

我有两个选择(如建议):

  • 将json文件与应用程序捆绑在一起,并在应用程序首次启动时加载
  • 生成sqlite数据库,并使用预填充的数据库发布应用程序
  • 对于第一种选择,我有以下顾虑:

    • 应用程序启动会很慢(因为解析一个20MB的文件,然后在核心数据中创建相应的记录需要一些时间)
    • 一旦文件被使用,就不需要应用程序正在使用的20MB空间。我认为无论如何都没有办法把那个文件处理掉,是吗
    对于第二种选择,我有以下顾虑:

    • 假设在我的应用程序的2.0版中,我想更新默认存储。例如,我在1.0版中提供的默认sqlite数据库出现了一些问题,或者我想添加更多的“默认”记录?我有多个实体,用户可能已经向其他实体添加了数据。因此,我无法替换sqlite数据库。那么,如何更新数据库中的记录呢
    我不知道拥有两个数据库是否真的更好,因为为了扩展功能,您通常会更改不止一个数据库

    对于数据库迁移,您可以使用如下内容

    首先使用核心数据的内部版本控制系统,并将当前使用的版本保存在
    NSUserDefaults
    中,在我的示例中保存在
    infoDictionary
    (您连接的.plist文件)中。因此,如果无法自动合并更改,您可以先尝试轻量级迁移,然后尝试manuel

    NSNumber *newDbVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"DBVersion"];
    NSNumber *oldDbVersion = [[NSUserDefaults standardUserDefaults] objectForKey:@"DBVersion"];
    
    NSURL *storeUrlOld;
    if(!oldDbVersion)
        storeUrlOld = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"default.sqlite"]]; // default path
    else
        storeUrlOld = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: [NSString stringWithFormat:@"db_%d.sqlite",[oldDbVersion intValue]]]];
    
    NSURL *storeUrlNew = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: [NSString stringWithFormat:@"db_%d.sqlite",[newDbVersion intValue]]]];
    
    NSString *path = [[NSBundle mainBundle] pathForResource:@"myDB" ofType:@"momd"];
    if(oldDbVersion)
        path = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"db_%d.mom", [oldDbVersion intValue]]];
    
    NSURL *momURLOld = [NSURL fileURLWithPath:path];
    NSLog(@"mom-path old: %@", path);
    NSLog(@"mom-url old: %@", momURLOld);
    
    NSManagedObjectModel *oldManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURLOld];
    
    // - - -
    
    path = nil;
    path = [[NSBundle mainBundle] pathForResource:@"db" ofType:@"momd"];
    path = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"db_%d.mom",[newDbVersion intValue]]];
    
    NSURL *momURLNew = [NSURL fileURLWithPath:path];
    NSLog(@"mom-path new: %@", path);
    NSLog(@"mom-url new: %@", momURLNew);
    NSManagedObjectModel *newManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURLNew];
    
    // # # # # # # # # # # # # # # # # # # # # #
    // - - - - Connect with old Database - - - -
    // # # # # # # # # # # # # # # # # # # # # #
    
    NSError *error;
    NSPersistentStoreCoordinator *persistentStoreCoordinatorOld = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:oldManagedObjectModel];
    
    // Allow inferred migration from the original version of the application.
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    
    if (![persistentStoreCoordinatorOld addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrlOld options:options error:&error]) 
    {
        // Handle the error
        NSLog(@"Failed to add old persistent store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    
        if(detailedErrors != nil && [detailedErrors count] > 0) 
        {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else 
        {
            NSLog(@"ERROR persistentStoreCoordinator: %@", [error userInfo]);
        }
        return;
    }
    
    NSManagedObjectContext *oldManagedObjectContext = [[NSManagedObjectContext alloc] init];
    [oldManagedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinatorOld];
    
    // # # # # # # # # # # # # # # # # # # # # #
    // - - - - Connect with new Database - - - -
    // # # # # # # # # # # # # # # # # # # # # #
    
    NSPersistentStoreCoordinator *persistentStoreCoordinatorNew = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: newManagedObjectModel];
    
    if (![persistentStoreCoordinatorNew addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrlNew options:options error:&error]) 
    {
        // Handle the error
        NSLog(@"Failed to add new persistent store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    
        if(detailedErrors != nil && [detailedErrors count] > 0) 
        {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else 
        {
            NSLog(@"ERROR persistentStoreCoordinator: %@", [error userInfo]);
        }
        return;
    }    
    
    NSManagedObjectContext *newManagedObjectContext = [[NSManagedObjectContext alloc] init];
    [newManagedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinatorNew];
    managedObjectContext = newManagedObjectContext;
    
    // # # # # # # # # # # # # # # # # # # # # # # #
    // - - - Transfere data from old DB to new - - -
    // # # # # # # # # # # # # # # # # # # # # # # #
    
    // - - -
    
    // # # # # # # # # #
    // - - - Users - - -
    // # # # # # # # # # 
    
    NSString *entityName = @"User";
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:oldManagedObjectContext];
    [request setEntity:entity];
    NSString *predicateFormat ;
    NSPredicate *predicate;
    error = nil;
    
    NSMutableArray *mutableFetchResultsUsers = [NSMutableArray arrayWithArray: [oldManagedObjectContext executeFetchRequest:request error:&error]];
    
    if (mutableFetchResultsUsers == nil) {
        // Handle the error.
    }
    NSLog(@"Users: %@", mutableFetchResultsUsers);
    for(User *user in mutableFetchResultsUsers)
    {
        NSLog(@"%@, %@, %@",user.userLogin,user.userDomain, user.serverAddress);
        User *userNew = [[DatabaseFactory sharedInstance] newObject:@"User"];
    [...] // do here integration
        userNew.attibute = user.attribute;
    
        [self saveContext];
    }
    [request release];
    request = nil;
    
    // next one
    

    希望我能帮你一点忙;)

    我最终使用了2个持久存储。一个用于“readwrite”数据库,另一个用于“readonly”(种子)数据库。在应用程序的未来版本中,我可以发布更新的种子数据库,而不会出现任何问题

    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    
        if (_persistentStoreCoordinator != nil) {
            return _persistentStoreCoordinator;
        }
    
        // Define the Core Data version migration options
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                 nil];
    
        // Attempt to load the persistent store
        NSError *error = nil;
        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    
        // Create the default/ user model persistent store
        {
            NSString *storeFileName = ...;
            NSString *configuration = @"Readwite";
            NSURL *storeURL = [[self applicationLocalDatabaseDirectory] URLByAppendingPathComponent:storeFileName];
    
            if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                           configuration:configuration
                                                                     URL:storeURL
                                                                 options:options
                                                                   error:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }
    
        // Create the seed data persistent store
        {
            NSURL *seedDataURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"SeedData" ofType:@"sqlite"]];
            NSString *configuration = @"SeedData";
    
            if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                           configuration:configuration
                                                                     URL:seedDataURL
                                                                 options:options
                                                                   error:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort();
                abort();
            }
        }
    
        // Developer's Note:
        // Instead of creating a single store, we created two persistent stores in an almost identical manner.
        // The only difference is that we explicitly named the configuration for the store to use, instead of
        // passing nil for the configuration parameter. Note that the configurations were set in xcdatamodeld file.
    
        return _persistentStoreCoordinator;
    }
    
    参考:


    根据您的解释,在一个持久性存储中使用多个实体与在两个存储和多个实体中使用多个实体相比会有什么问题?我看不出有什么理由不能用多个实体来完成同样的事情。这样,您只需将所有数据预加载到一个实体中,然后在完成操作后删除该实体中的所有对象。顺便说一句,要删除文件,请尝试[[NSFileManager defaultManager]RemoveItemAttribute:myLocalURL error:&error];好的,我可以为Entity X预加载sqlite数据库,并将其与我的应用程序v1.0一起发布。现在,当我必须更改一些条目时,我该怎么办。。。并更新v2.0中实体X的默认数据库?我无法从捆绑包中删除文件,可以吗?如果您的json文件是项目结构中的一个简单文件,您应该可以使用NSFileManager()删除它