我目前正在編寫一個需要修改和保存各種數據片段的應用程序。我決定爲此使用Core Data。 當用戶首次打開應用程序時,我需要從sqlite數據庫導入大量數據,這些數據由多對多關係組成。來自SQLite數據庫的核心數據「Upsert」
我想找出將所有這些數據插入我的代碼數據存儲的最佳方法。現在,我正在使用NSOperation來執行導入,而應用程序的其餘部分仍處於活動狀態,因此用戶可以執行其他操作,但我希望導入過程儘快發生,以便可以立即訪問整個應用程序。
我現在使用的方法是使用NSFetchRequest嘗試在數據存儲中查找相關實體,如果實體在那裏,我只是將它作爲關係添加,如果實體不存在,我創建一個新的,並添加它作爲一種關係。這有效,但我覺得它可能不是最佳的。
的代碼我現在使用:
- (void)importEntitiesIntoContext: (NSManagedObjectContext*)managedObjectContext
{
// Setup the database object
static NSString* const databaseName = @"DBName.sqlite";
NSString* databasePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: databaseName];
sqlite3* database;
// Open the database from the user's filessytem
if (sqlite3_open_v2([databasePath UTF8String], &database, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK)
{
// Setup the SQL Statement
NSString* sqlStatement = [NSString stringWithFormat: @"SELECT some_columns FROM SomeTable;"];
sqlite3_stmt* compiledStatement;
if (sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Create objects to test for existence of exercises
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"something == $SOME_NAME"];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName: @"SomeEntity"
inManagedObjectContext: managedObjectContext];
NSFetchRequest* fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity: entityDescription];
// Loop through the results and add them to the feeds array
while (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSString* someName = [NSString stringWithCharsIfNotNull: (char*)sqlite3_column_text(compiledStatement, 1)];
NSPredicate* localPredicate = [predicate predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObject: someName
forKey: @"SOME_NAME"]];
[fetchRequest setPredicate: localPredicate];
NSError* fetchError;
NSArray* array = [managedObjectContext executeFetchRequest: fetchRequest
error: &fetchError];
if (array == nil)
{
// handle error
}
else if ([array count] == 0)
{
SomeEntity* entity =
[NSEntityDescription insertNewObjectForEntityForName: @"SomeEntity"
inManagedObjectContext: managedObjectContext];
entity.name = someName;
// **here I call a method that attempts to add the relationships(listed below)**
}
else
{
// Some entity already in store
}
}
}
else
{
NSLog(@"sqlStatement failed: %@", sqlStatement);
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
// All the data has been imported into this temporary context, now save it
NSError *error = nil;
if (![managedObjectContext save: &error])
{
NSLog(@"Unable to save %@ - %@", [error localizedDescription]);
}
}
方法添加的關係:
- (void)setRelationshipForEntity: (Entity*)entity
inManagedObjectContext: (NSManagedObjectContext*)managedObjectContext
usingDatabase: (sqlite3*)database
entityId: (NSNumber*)entityId
{
// Setup the SQL Statement and compile it for faster access
NSString* sqlStatement = [NSString stringWithFormat: @"SELECT Relationship.name FROM Relationship JOIN Entitys_Relationship ON Entitys_Relationship.id_Relationship = Relationship.id JOIN Entitys ON Entitys_Relationship.id_Entitys = Entitys.id WHERE Entitys.id = %d;", [entityId integerValue]];
sqlite3_stmt* compiledStatement;
if (sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Create objects to test for existence of relationship
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"relationshipName == $RELATIONSHIP_NAME"];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName: @"EntityRelationship"
inManagedObjectContext: managedObjectContext];
NSFetchRequest* fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity: entityDescription];
while (sqlite3_step(compiledStatement) == SQLITE_ROW)
{
NSString* relationshipName = [NSString stringWithCharsIfNotNull: (char*)sqlite3_column_text(compiledStatement, 0)];
NSPredicate* localPredicate = [predicate predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObject: relationshipName
forKey: @"RELATIONSHIP_NAME"]];
[fetchRequest setPredicate: localPredicate];
NSError* fetchError;
NSArray* array = [managedObjectContext executeFetchRequest: fetchRequest
error: &fetchError];
if (array == nil)
{
// handle error
}
else if ([array count] == 0)
{
EntityRelationship* entityRelationship =
[NSEntityDescription insertNewObjectForEntityForName: @"EntityRelationship"
inManagedObjectContext: managedObjectContext];
entityRelationship.relationshipName = relationshipName;
[entity addRelationshipObject: entityRelationship];
//NSLog(@"Inserted relationship named %@", relationshipName);
}
else
{
[entity addRelationship: [NSSet setWithArray: array]];
}
}
}
else
{
NSLog(@"slqStatement failed: %@", sqlStatement);
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
信息是在sqlite數據庫中,用戶將能夠更改其個人設備上的信息,但對於應用程序更新,數據將需要與新數據合併。 – jessecurry 2010-01-04 17:54:14
我仍然會這樣做,以便合併在設備上的用戶Core Data存儲和應用程序的更新初始Core Data存儲之間,但這是因爲我更喜歡使用Core Data。 – gerry3 2010-01-04 18:05:30
您通常使用什麼方法創建初始CoreData存儲? – jessecurry 2010-01-05 00:26:37