可以使用两个单独的SQLite数据库吗?

时间:2010-10-16 01:37:27

标签: iphone database sqlite core-data

我有一个sqlite数据库,我在其中存储用户定义的信息和对用户只读的信息。我觉得将来可能需要修改只读信息,我不想进行整个数据迁移。有没有办法可以使用一个单独的sqlite数据库,可以很容易地替换为只读信息?如果是这样,你能否就如何做到这一点给出一点指示?我很困惑,因为我目前在xcdatamodel上有所有实体 - 我会创建两个数据模型吗?不确定这是怎么回事。提前谢谢。


这不起作用,但请随时提供反馈。

- (NSManagedObjectModel *)managedObjectModel {

    NSLog(@"%s", __FUNCTION__);
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    //managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];

    NSString *mainPath = [[NSBundle mainBundle] pathForResource:@"MyApp" ofType:@"mom"];
    NSURL *mainMomURL = [NSURL fileURLWithPath:mainPath];
    managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:mainMomURL];

    [managedObjectModel setEntities:[NSArray arrayWithObjects:
                                          [[managedObjectModel entitiesByName] objectForKey:@"Version"],
                                          [[managedObjectModel entitiesByName] objectForKey:@"Book"],
                                          nil] forConfiguration:@"info"];

    [managedObjectModel setEntities:[NSArray arrayWithObjects:
                                          [[managedObjectModel entitiesByName] objectForKey:@"Settings"],
                                          [[managedObjectModel entitiesByName] objectForKey:@"Persons"],
                                          nil] forConfiguration:@"main"];

    return managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    NSLog(@"%s", __FUNCTION__);
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Main.sqlite"];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"Default" ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];    


    NSString *infoStorePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Info.sqlite"];
    if (![fileManager fileExistsAtPath:infoStorePath]) {
        NSString *defaultInfoStorePath = [[NSBundle mainBundle] pathForResource:@"DefaultInfo" ofType:@"sqlite"];
        if (defaultInfoStorePath) {
            [fileManager copyItemAtPath:defaultInfoStorePath toPath:infoStorePath error:NULL];
        }
    }

    NSURL *infoStoreUrl = [NSURL fileURLWithPath:infoStorePath];

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    //persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] init]; 

    NSPersistentStore *mainStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"main" URL:storeUrl options:options error:&error];
    NSPersistentStore *infoStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"verses" URL:infoStoreUrl options:options error:&error];

    NSManagedObject *settingsEntity = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Settings"] insertIntoManagedObjectContext:self.managedObjectContext];
    [self.managedObjectContext assignObject:settingsEntity toPersistentStore:mainStore];

    NSManagedObject *persons = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Persons"] insertIntoManagedObjectContext:self.managedObjectContext];
    [self.managedObjectContext persons toPersistentStore:mainStore];

NSManagedObject *version = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Version"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext assignObject:version toPersistentStore:infoStore];

NSManagedObject *book = [[NSManagedObject alloc] initWithEntity:[[managedObjectModel entitiesByName] objectForKey:@"Book"] insertIntoManagedObjectContext:self.managedObjectContext];
[self.managedObjectContext assignObject:book toPersistentStore:infoStore];

- (NSManagedObjectContext *)managedObjectContext {

    NSLog(@"%s", __FUNCTION__);
    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [NSManagedObjectContext new];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}

4 个答案:

答案 0 :(得分:3)

文档的部分答案:

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/CoreData/Articles/cdMOM.html

  

配置

     

配置有一个名称和一个   相关的实体集。集合   可能重叠 - 即给定的实体   可能出现在多个   组态。你建立   以编程方式使用配置   setEntities:forConfiguration:或using   Xcode数据建模工具(见   用于核心数据的Xcode工具)和   检索给定的实体   配置名称使用   entitiesForConfiguration:

     

您通常使用配置   你想存储不同的实体   在不同的商店。一个持久的   商店协调员只能有一个   托管对象模型,默认情况下   与给定相关的每个商店   协调员必须包含相同的内容   实体。解决这个问题   限制,你可以创建一个模型   包含所有的联合   您要使用的实体。然后是你   在模型中创建配置   每个实体的子集   你想用。然后你可以使用它   创建协调器时的模型。   添加商店时,请指定   不同的商店属性   组态。在创作时   但是,请记住你的配置   你无法创建跨店   关系。

然后,NSPersistentStoreCoordinator允许您创建多个存储,每个存储具有不同的配置。

任何人都有一个如何做到这一切的例子吗?

答案 1 :(得分:3)

您实际上可以使用单个数据模型来完成此任务,但是您需要手动(在代码中)将实体分配给不同的NSPersistentStore实例,只需要一些代码:

NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] init];
NSPersistentStore *userStore = [coord addPersistentStoreWithType:NSSQLiteStore configuration:nil URL:someFileURL options:someoptions error:&error];
NSPersistentStore *otherStore = [coord addPersistentStoreWithType:NSSQLiteStore configuration:nil URL:someFileURL2 options:someoptions error:&error];

//Now you use the two separate stores through a managed object context that references the coordinator
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coord];

NSManagedObject *userObject = [[NSManagedObject alloc] initWithEntity:entityDescFromModel insertIntoManagedObjectContext:context];
[context assignObject:userObject toPersistentStore:userStore];

NSManagedObject *otherObject = [[NSManagedObject alloc] initWithEntity:entityDescFromModel insertIntoManagedObjectContext:context];
[context assignObject:otherObject toPersistentStore:otherStore];

通过这种方式,您始终可以指定保留对象的商店。一旦对象位于各自的商店中,我认为您不必再​​执行任何额外的工作,即您应该只能执行在引用两个商店的协调器的上下文中获取规范。

答案 2 :(得分:2)

嗯,这就是我最终做的事情。两个managedObjectModels,两个managedObjectContexts,两个persistentStoreCoordinators,因此有两个持久存储。完全分开,这很好,因为两个商店中的数据根本没有关系。以下是为什么sqlite文件在没有实体且根本没有数据的情况下创建的原因:在创建实体之前,您需要在db中执行至少一个获取请求。谁知道?好吧,显然,不是我。无论如何,这对我来说效果很好,因为在应用程序启动之前我甚至都没有准备好第二个商店(这是一个额外的功能)。现在,当我的数据文件最终准备就绪时,我可以添加sqlite文件,取消注释与其相关的代码,并将应用程序发送到应用商店。它不会触及商店中的用户数据。而且,我将把我的只读存储保存在我的包中,所以不需要迁移。那声音怎么样?

答案 3 :(得分:0)

好的,我发现了如何添加其他数据模型。文件>新文件> Iphone OS>资源>数据模型。将我的实体移动到该数据模型。编译并似乎运行,但没有数据。问题是,仍然只有一个sqlite文件。需要了解如何使用两个,并将每个与适当的模型相关联。然后,应该能够在应用更新时覆盖新模型的默认sqlite文件。但我认为,我仍然需要进行迁移,因为它会在我指定的默认文件中在iPhone上创建一个sqlite文件。它不应该是一个艰难的迁移,我希望,因为我不会在文件中有任何用户数据。学习,但仍然有任何进一步的帮助。