2010-01-04 5 views
1

현재 다양한 데이터를 수정하고 유지해야하는 응용 프로그램을 작성 중입니다. 이 목적으로 핵심 데이터를 사용하기로 결정했습니다. 사용자가 처음으로 응용 프로그램을 열면 sqlite 데이터베이스에서 많은 양의 데이터를 가져와야합니다.이 데이터는 다 대다 관계로 구성됩니다.SQLite 데이터베이스의 핵심 데이터 "Upsert"

모든 데이터를 코드 데이터 저장소에 삽입하는 가장 좋은 방법을 찾고 싶습니다. 지금은 NSOperation을 사용하여 나머지 응용 프로그램을 활성 상태로 유지하면서 사용자가 다른 작업을 수행 할 수 있도록 가져 오기를 수행하지만 최대한 빨리 가져 오기를 수행하여 전체 App에 즉시 액세스 할 수있게하고 싶습니다. .

내가 지금 사용하고있는 방법은 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 데이터베이스에 있으면 사용자는 개인 장치의 정보를 변경할 수 있지만 App 업데이트의 경우 데이터를 새 데이터와 병합해야합니다. – jessecurry

+0

병합을 장치의 사용자 코어 데이터 저장소와 응용 프로그램의 업데이트 된 초기 코어 데이터 저장소간에 병합하도록 했으므로 핵심 데이터 작업을 선호하기 때문입니다. – gerry3

+0

초기 CoreData 저장소를 만드는 데 일반적으로 어떤 방법을 사용합니까? – jessecurry

2

애플이 코어 데이터 저장소로 큰 수입을 최적화하는 방법에 대한 몇 가지 제안이 있습니다

  • 일괄 가져 오는 동안 실행 취소 매니저를 사용하지 않도록 설정을
  • 기록별로 레코드를 삽입하지 마십시오 - 일괄 만들기 크기 n (레코드 크기에 따라)
  • 은 자세한 내용은 documentation을 참조 로컬 오토 릴리즈 풀을 사용하여 각 배치

후 드레인.