Je suis en train d'écrire une application qui a besoin de la possibilité de modifier et de conserver diverses données. J'ai décidé d'utiliser Core Data à cette fin. Lorsque l'utilisateur ouvre l'application pour la première fois que j'ai besoin d'importer une grande quantité de données à partir d'une base de données sqlite, ces données sont composées des relations plusieurs-à-plusieurs.Core Data "Upsert" de base de données SQLite
Je voudrais trouver la meilleure façon d'insérer toutes ces données dans mon magasin de données de code. Actuellement, j'utilise une NSOperation pour faire l'importation alors que le reste de l'application reste actif, donc l'utilisateur peut faire d'autres choses, mais j'aimerais que l'importation se fasse le plus rapidement possible pour que l'application entière soit accessible immédiatement . La méthode que j'utilise maintenant est d'utiliser un NSFetchRequest pour tenter de trouver l'entité associée dans le magasin de données, si l'entité est là, je l'ajoute juste comme une relation, si l'entité n'est pas là, je crée un nouveau et l'ajouter comme une relation. Cela fonctionne, mais je pense que ce n'est probablement pas proche de l'optimum.
Le code J'utilise maintenant:
- (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]);
}
}
Méthode d'ajouter les relations:
- (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);
}
l'information est dans une base de données sqlite, l'utilisateur sera en mesure de modifier les informations sur leur appareil personnel, mais pour les mises à jour de l'application, les données devront être fusionnées avec de nouvelles données. – jessecurry
Je l'aurais toujours pour que la fusion se fasse entre le magasin de données principales d'un utilisateur sur l'appareil et le magasin initial de données de base mis à jour de l'application, mais c'est parce que je préfère travailler avec Core Data. – gerry3
Quelle méthode utilisez-vous généralement pour créer le magasin CoreData initial? – jessecurry