Domanda

Attualmente sto scrivendo un'app che necessita della possibilità di modificare e rendere persistenti vari dati.Ho deciso di utilizzare Core Data per questo scopo.Quando l'utente apre l'applicazione per la prima volta, ho bisogno di importare una grande quantità di dati da un database SQLite, questi dati sono costituiti da relazioni molti-a-molti.

Mi piacerebbe scoprire il modo migliore per inserire tutti questi dati nel mio archivio dati di codice.In questo momento sto utilizzando una NSOperation per eseguire l'importazione mentre il resto dell'applicazione rimane attivo, in modo che l'utente possa fare altre cose, ma vorrei che l'importazione avvenisse il più rapidamente possibile in modo che sia possibile accedere immediatamente all'intera app .

Il metodo che sto utilizzando ora è utilizzare una NSFetchRequest per tentare di trovare l'entità correlata nell'archivio dati, se l'entità è presente la aggiungo semplicemente come relazione, se l'entità non è presente ne creo una nuova e aggiungilo come relazione.Funziona, ma sento che probabilmente non è nemmeno vicino all'ottimale.

Il codice che sto usando ora:

- (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] );
    }
}

Metodo per aggiungere le relazioni:

- (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 );  
}
È stato utile?

Soluzione

Dove si trova il database originale proviene?

In genere, si convertire tutti i tuoi dati a Core Data durante lo sviluppo e poi spedire l'applicazione con un negozio di dati principale pre-popolato (senza bisogno di un utente di aspettare per l'importazione).

Altri suggerimenti

Apple ha alcuni suggerimenti su come ottimizzare le grandi importazioni in un archivio Core Data:

  • Disabilita il gestore annullamenti durante l'importazione batch
  • Non inserire record per record: crea batch di dimensione n (a seconda della dimensione del record)
  • Utilizzare un pool di rilascio automatico locale e svuotarlo dopo ogni batch

Vedi il documentazione per i dettagli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top