我知道这个话题已经讨论过,但我正在寻找一个特定的解决方案,这个解决方案已在任何地方讨论过,即使用多个存储而不是一个 - 一个用于默认数据,另一个用于用户输入的数据。
在我的应用程序中,我想为实体X(仅限)预加载大量数据,即20 MB json文件。该模型还包含实体Y和实体Z.我认为最适合我需求的解决方案如下:
使用两个sqlite数据库。仅适用于Entity X的一个数据库,可在应用程序的未来版本中替换...而不会影响实体Y和实体Z的数据(毫不费力)。
详情(仅限于案例):
我有两个选择(如建议的那样):
有了第一个选项,我有以下问题:
有了第二个选项,我有以下问题:
答案 0 :(得分:0)
我不知道拥有2个数据库是否真的更好,因为你所做的改变主要不仅仅是扩展功能。
对于数据库迁移,您可以使用类似的内容。
首先使用核心数据的内部版本控制系统,并在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
希望我能帮助你一点;)
答案 1 :(得分:0)
我最终使用了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;
}
参考: