我正在构建一个依赖于3个独立的.sqlite数据库的应用程序。我的App Delegate中有哪些方法可以编辑以允许这样做?目前,我的managedObjectContext
和managedObjectModel
尚未触及模板创建方式。我的persistantStoreCoordinator
看起来像这样:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil)
{
return _persistentStoreCoordinator;
}
NSURL *storeURLConfigA = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dbA.sqlite"];
NSURL *storeURLConfigB = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dbB.sqlite"];
NSURL *storeURLConfigC = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"dbC.sqlite"];
// // Pre-load .sqlite db in Project Navigator into app on first run after deleting app
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURLConfigA path]])
// dbA
{
NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"dbA" ofType:@"sqlite"]];
NSError* err = nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURLConfigA error:&err])
{
NSLog(@"Error preloading database A - %@",error.description);
}
}
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURLConfigB path]])
// dbB
{
NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"dbB" ofType:@"sqlite"]];
NSError* err = nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURLConfigB error:&err])
{
NSLog(@"Error preloading database B - %@",error.description);
}
}
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURLConfigC path]])
// dbC
{
NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"dbC" ofType:@"sqlite"]];
NSError* err = nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURLConfigC error:&err])
{
NSLog(@"Error preloading database C - %@",error.description);
}
}
// // Put the Configs into the PersistantStoreCoordinator and tie them to their database file
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = @{NSSQLitePragmasOption : @{@"journal_mode": @"DELETE"}};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"Config_A" URL:storeURLConfigA options:options error:&error])
{
NSLog(@"Error setting up dbA - %@",error.description);
abort();
}
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"Config_B" URL:storeURLConfigB options:options error:&error])
{
NSLog(@"Error setting up dbB - %@",error.description);
abort();
}
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"Config_C" URL:storeURLConfigC options:options error:&error])
{
NSLog(@"Error setting up dbC - %@",error.description);
abort();
}
return _persistentStoreCoordinator;
}
然后,我的mainBundle
中有一个单独的.xcdatamodelID,其中包含所有三个数据库中的所有表/实体。除Config_A
配置外,我还使用XCode的CoreData编辑器界面添加配置Config_B
,Config_C
和Default
。我已将实体移动到我希望它们所在的数据库的配置中(每个实体应该只在一个数据库中)。
我运行应用程序,一切运行正常,我可以毫无问题地读写数据。当我查看表格时(例如通过终端或Firefox的SQLite Manager),问题就出现了。所有3个数据库都包含所有表,但这些表只包含它们应该存在的数据库中的数据(其他两个数据库中该表中有0行)。
为什么每个数据库中的所有表都是?如何让每个数据库只包含我希望它们拥有的几个表?
答案 0 :(得分:1)
您已将所有3个数据库(NSPersistentStores)添加到同一个NSPersistentStoreCoordinator。因此,当您对托管对象上下文执行保存时,商店协调员会将这些更改分发到其所有商店。相反,为每个数据库创建一个持久性存储协调器,可能将它们保存在NSDictionary中,A数据库持久性存储协调器的键为“A”,B数据库协调器的键为“B”,等等。然后在创建时在新的托管对象上下文中,您必须确定它属于哪个数据库(NSPersistentStoreCoordinator)。这将允许您将表/更改分开,并防止所有数据进入所有3个数据库。
答案 1 :(得分:0)
我从Patrick Goley的回答开始,但我仍然无法得到我想要的行为。在阅读了他所拥有的内容之后,我有了一个想法,就是把我的三个数据库分成完全独立的部分到处都能想到这样做,而这似乎正在起作用。如果有人需要我发布我的整个应用代表,我会,但其主旨是:
我有3 NSManagedObjectContext
s,3 NSManagedObjectModel
s和3 NSPersistantStoreCoordinator
s的属性。
我复制了工厂方法以创建每个(最初是在我从模板创建应用程序时编写的)并且每个方法都硬编码以使用适当的上下文/模型/商店协调员。
我有3个NSSet
来保存它各自数据库的表名,当我想读取(或保存到)一个表时,我传递该表的名称,然后使用NSSet
以获取适当的上下文/模型/商店协调员。
在花了很多时间阅读我能找到的所有Apple文档和其他主题后,我觉得不应该支持单独的数据库这么难,但这是唯一真正做我想做的事情至今。我不知道我之前缺少什么,但这是有效的,所以它现在会做。如果我将来有更多的空闲时间,我可能会更多地研究它并尝试找出正确的方法,如果我发现它,我会更新。