Можно ли использовать две отдельные базы данных SQLite? - PullRequest
3 голосов
/ 16 октября 2010

У меня есть одна база данных 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 ]

3 голосов
/ 17 октября 2010

На самом деле вы можете использовать одну модель данных для достижения этой цели, однако вам нужно вручную (в коде) назначать сущности различным экземплярам 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];

Таким образом, вы всегда можете указать, в каком хранилище хранятся объекты. Я не думаю, что вам придется выполнять какую-либо дополнительную работу, когда объекты находятся в соответствующих хранилищах, т.е. вы просто должны иметь возможность выполнить получить спецификацию в контексте, который ссылается на координатор для обоих магазинов.

3 голосов
/ 16 октября 2010

Частичный ответ из документов:

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

Конфигурации

Конфигурация имеет имя и связанный набор сущностей.Наборы могут перекрываться, то есть данный объект может появляться в нескольких конфигурациях.Вы устанавливаете конфигурации программно, используя setEntities: forConfiguration: или используя инструмент моделирования данных XCode (см. Инструменты XCode для базовых данных), и извлекаете сущности для данного имени конфигурации, используя entityForConfiguration:.

Обычно вы используете конфигурации, если выхочу хранить разные объекты в разных магазинах.Координатор постоянного хранилища может иметь только одну модель управляемых объектов, поэтому по умолчанию каждое хранилище, связанное с данным координатором, должно содержать одинаковые объекты.Чтобы обойти это ограничение, вы можете создать модель, содержащую объединение всех сущностей, которые вы хотите использовать.Затем вы создаете конфигурации в модели для каждого из подмножеств объектов, которые вы хотите использовать.Затем вы можете использовать эту модель при создании координатора.Когда вы добавляете магазины, вы указываете различные атрибуты магазина по конфигурации.Однако, когда вы создаете свои конфигурации, помните, что вы не можете создавать взаимосвязи между хранилищами.

Тогда NSPersistentStoreCoordinator позволяет создавать несколько хранилищ, каждое из которых имеет свою конфигурацию.

Любой имеетпример того, как все это сделать?

2 голосов
/ 21 октября 2010

Ну, вот что я в итоге сделал. Два managedObjectModels, два managedObjectContexts, два persistentStoreCoordinators и, следовательно, два постоянных хранилища. Все абсолютно раздельно, и это нормально, поскольку между данными в двух хранилищах вообще нет никакой связи. И здесь есть подсказка, почему файлы sqlite создаются без сущностей и вообще без данных: прежде чем сущности даже будут созданы, вам нужно выполнить хотя бы один запрос на выборку в БД. Кто знал? Ну, очевидно, не я. В любом случае, это хорошо работает для меня, поскольку у меня даже не будет готово второе хранилище до тех пор, пока приложение не будет запущено (это для дополнительной функции). Теперь, когда мой файл данных, наконец, готов, я могу просто добавить файл sqlite, раскомментировать соответствующий код и отправить приложение в магазин приложений. Это не затронет магазин с пользовательскими данными. И я собираюсь сохранить свое хранилище только для чтения в моем комплекте, так что никакой миграции. Как это звучит?

0 голосов
/ 16 октября 2010

Хорошо, я узнал, как добавить другую модель данных. Файл> Новый файл> ОС Iphone> Ресурс> Модель данных. Переместил мои сущности в эту модель данных. Скомпилировано и, кажется, работает, но без данных. Проблема в том, что все еще есть только один файл sqlite. Необходимо выяснить, как использовать два, и связать каждого с соответствующей моделью. Затем должен быть в состоянии перезаписать файл sqlite по умолчанию для новой модели при обновлении приложения. НО мне все равно придется выполнить миграцию, я думаю, поскольку на iPhone будет создан файл sqlite из указанного по умолчанию файла. Надеюсь, это не должно быть трудной миграцией, поскольку в файле не будет никаких пользовательских данных. Учусь, но все равно, буду признательна за любую дополнительную помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...