2010-01-04 55 views
1

我目前正在編寫一個需要修改和保存各種數據片段的應用程序。我決定爲此使用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); 
} 

回答

1

哪裏原始數據庫是從哪裏來的?

通常,您可以在開發期間將所有數據轉換爲核心數據,然後將應用程序與預先填充的核心數據存儲一起發送(不需要用戶等待導入)。

+0

信息是在sqlite數據庫中,用戶將能夠更改其個人設備上的信息,但對於應用程序更新,數據將需要與新數據合併。 – jessecurry 2010-01-04 17:54:14

+0

我仍然會這樣做,以便合併在設備上的用戶Core Data存儲和應用程序的更新初始Core Data存儲之間,但這是因爲我更喜歡使用Core Data。 – gerry3 2010-01-04 18:05:30

+0

您通常使用什麼方法創建初始CoreData存儲? – jessecurry 2010-01-05 00:26:37

2

蘋果公司如何大量進口到優化核心數據存儲的一些建議:

  • 批量導入過程中禁用撤消經理
  • 不要插入記錄的記錄 - 創建的批次大小n(根據記錄大小)
  • 使用本地自動釋放池每批

後瀝乾它見documentation的細節。