2010-05-13 8 views
1

J'ai un objet NetworkMember qui n'a aucun attribut mais qui est défini par ses relations Personne, Réseau, Niveau et Rôle. Dans mon application, j'ai trouvé toutes les quatre relations, mais je veux m'assurer de ne pas enregistrer en double mon NetworkMember, ainsi je voudrais rechercher ce NSManagedObject avant de l'instancier.Données de base: récupérer un objet NSManagedObject par ses propriétés

Comment écrire une requête qui interroge un objet NSManagedObject composé uniquement de relations?

Vive

Nik

Répondre

4

Vous pouvez écrire un NSPredicate contre des relations comme vous le feriez pour des attributs.

Par exemple:

- (BOOL)isPerson:(Person *)person memberOfNetwork:(Network *)network { 
    // assume NetworkMember entity is ivar networkMemberEntity_ 
    // assume NSManagedObjectContext is ivar context_ 

    NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; 
    [fetch setEntity:networkMemberEntity_]; 
    [fetch setPredicate:[NSPredicate predicateWithFormat: 
     @"(person == %@) AND (networks CONTAINS %@)", person, network]]; 
    [fetch setFetchLimit:1]; 

    NSError *error = nil; 
    NSInteger count = [context_ countForFetchRequest:fetch error:&error]; 
    if (count < 0) { 
     // always handle errors in real code 
     // and never check for errors using "error == nil" 
    } 

    return count > 0; 
} 

Dans le cas où vous présentez, cependant, vous devriez sérieusement considérer si vous avez vraiment besoin de le faire. Il semble que vous essayez de modéliser une relation plusieurs-à-plusieurs entre la personne et le réseau. Si vous venez d'un arrière-plan de base de données, vous pourriez penser que vous avez besoin d'une table de jointure pour cela et créer une entité intermédiaire. Toutefois, Core Data peut gérer tout cela pour vous; vous pouvez créer une relation plusieurs-à-plusieurs directement entre la personne et le réseau et ne pas avoir à gérer vous-même une entité ou une table intermédiaire. Tout comme vous n'avez pas à vous soucier des clés primaires et étrangères lorsque vous traitez des relations dans les données de base, le framework traite ce genre de chose pour vous, vous permettant de travailler au niveau de l'objet.

+0

Merci beaucoup, c'est ainsi que j'espérais que cela pourrait être fait. :-) – niklassaers

+0

Juste une petite correction: fetch devrait être libéré à un certain point, soit en appelant autorelease après init ou en envoyant une version avant le retour. Incidemment, Chris, vos articles de blog ont été d'une aide énorme avec d'autres problèmes de données de base, alors merci! –

1

Vous pouvez utiliser un NSPredicate avec des chemins clé-valeur pour faire référence aux relations que le prédicat à un NSFetchRequest. Par exemple:

NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
[request setEntity:[NSEntity entityForName:@"NetworkMember" inManagedObjectContext:managedObjectContext]; 
[request setPredicate:[NSPredicate predicateWithFormat:@"person.name == %@ AND ANY (roles.name == \"Manager\")", name]]; 
NSInteger count = [managedObjectContext countForFetchRequest:request error:&error]; 
[request release]; 
if (error) { /* handle the error */ } 
if (count != 0) { /* do something if the member already exists */ } 

Si tout ce que vous avez besoin est de confirmer l'existence d'un objet particulier, vous pouvez utiliser la méthode countForRetchRequest:error: pour voir combien d'objets seraient retourné si vous exécutez la requête d'extraction. Si vous faites beaucoup de tests, cela peut être beaucoup plus efficace.

+0

Il n'est donc pas possible d'interroger par les ID que Core Data utilise autrement dans les coulisses de la base de données SQLite3? – niklassaers

+0

Vos données ne sont pas nécessairement stockées dans une base de données sqlite. Core Data prend également en charge les formats XML et binaires, il n'est donc pas correct de considérer les données de base comme une base de données. Les données de base ont la classe 'NSManagedObjectID' pour identifier de façon unique chaque objet, et il existe des méthodes que vous pouvez utiliser pour obtenir des objets basés sur ces ID. – Alex

+1

Vous ne devez pas compter sur l'attribut '-objectID' car il peut changer et change. La seule fois où vous devriez l'utiliser est quand vous passez des références entre les threads. Autre que cela ne comptez pas sur lui. Si vous avez besoin d'un unique, créez le vôtre. –

Questions connexes