Fetch sur plusieurs entités (to-one)

Bonjour,


 


J'ai besoin d'un éclaircissement concernant un fetch sur 2 entités (one to one).


J'ai plusieurs entités mais bon commençons juste avec 2:  Person <---> Address (to-one)


Pour récupérer l'adresse d'une personne dont j'obtiens juste le nom via le tableView, je procède ainsi:


 


//Pour obtenir la personne



 
 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    NSEntityDescription *entityPerson = [NSEntityDescription entityForName:@Person inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entityPerson];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@lastName = %@", personChoice];
    NSArray *idClientArray = [detailMutableArray filteredArrayUsingPredicate:predicate];
    [fetchRequest setPredicate:predicate];
 
  NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@lastName ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
 
NSError *error = nil;
    idClientArray = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

Pour obtenir l'adresse, est-ce que je peux procéder comme suit:



Person *person;
NSManagedObject *address = person.r_address;
//r_address est le nom de ma relation

Je récupère toujours une adresse "Null".


Pouvez-vous m'aider svp?


 


Merci


Réponses

  • En procédant ainsi tu risques d'avoir un problème si plusieurs personnes ont le même nom.


    À quoi te sert :



    NSArray *idClientArray = [detailMutableArray filteredArrayUsingPredicate:predicate];

    Le code qui suit est douteux :



    Person *person;
    NSManagedObject *address = person.r_address;

    Il est instancié comment ton objet person ?


  • En fait detailMutablearray contient la liste de toutes les personnes mais maintenant que tu en parles c'est une information redondante.


    J'ai voulu instancié mon objet personne comme ceci


    person = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:&error] lastObject];

     


    Mais j'obtiens toujours une adresse Null.


    Concernant :



     


     


    En procédant ainsi tu risques d'avoir un problème si plusieurs personnes ont le même nom.

    Je dois faire un predicate sur le nom et sur le prénom alors c'est bien ça?


     


     


    Merci




  •  


    Mais j'obtiens toujours une adresse Null.


    Concernant :


    Je dois faire un predicate sur le nom et sur le prénom alors c'est bien ça?


     


     


    Merci




     


    Pas vraiment. Dans ton premier post tu parles d'une table view où tu récupère juste le nom d'un personne. Je ne saisis pas vraiment : tu dois récupérer ce nom lors de la sélection d'une ligne de ta table view ? Si oui, pourquoi ne pas récupérer directement l'objet Person associé à  l'index de sélection de ta table view ? Ca serait carrément plus simple !

  • Je dois récupérer ce nom pour pouvoir retrouver l'adresse par la suite mais je ne vois pas exactement ce que tu veux dire. 


    En fait je récupère la personne grâce l'index de la tableView et ensuite je passe le nom de cette personne à  la vue détail. 


    Dans la vue détail j'effectue un fetchrequest avec un predicate dessus pour récupérer toutes les informations concernant cette personne à  savoir: nom, prénom, âge, (adresse complète.....) ect.


    Mais je n'arrive pas à  récupérer l'adresse de cette personne.


    Je pensais que récupérer les infos entre entités (one-to-one) était relativement simple...mais c'est pas mon cas.  ::)

  • AliGatorAliGator Membre, Modérateur
    Quand tu tap sur une row de ta tableView et récupère la Person* p associée d'après l'indexPath, pourquoi passer ensuite seulement le nom de la personne au viewController suivant, pourquoi ne pas carrément lui passer l'objet Person* p directement ? Voire l'objet p.r_address même ?

    C'est un peu dommage alors que tu as l'objet Person représentant directement la personne cliquée, de ne passer que son nom au VC suivant et de demander au VC suivant de refaire un Fetch de son côté pour retomber si l'objet Person dont on est parti... sans compter comme te l'a mentionné Kubernan que du coup si tu as 2 personnes avec le même lastName et que tu ne passés que le lastName comme valeur pour retrouver la Person dans le 2e VC, si tu as 2 personnes VC le même lastName tu vas avoir des soucis... donc en plus de te compliquer la vie à  faire Person -> lastName -> Person -> r_address, tu risques des incohérences, alors qu'il est tellement plus simple de faire juste Person -> r_address !!
  • IBimiIBimi Membre
    juillet 2013 modifié #7

    Woaw... quelle économie de code en effet c'est bien mieux comme ça mais je n'arrive toujours pas à  récupérer mon adresse.


    L'adresse est toujours "Null", voici ce que j'obtiens en output:


     


     


     


    data: {


        age = 72;


        birthDate = "1940-07-30 05:00:00 +0000";


        email = "11111@hot.com";


        firstName = Un;


        gender = Homme;


        lastName = Premier;


        notes = nil;


        objectif = "Bien \U00eatre personnel";


        "r_idAddress" = nil;


        "r_idMeasure" = nil;


        "r_idRisko" = nil;


        "r_idTelephone" = "<relationship fault: 0x81894c0 'r_idTelephone'>";


    })


     


    Toutes mes relations (one-to-one) sont à  nil, est-ce normal?


    Quant à  ma relation "r_idTelephone" en fault c'est normal selon la doc(je ne vous apprends rien...  ::) ).


    Comment puis je maintenant obtenir l'adresse de cette personne sachant qu'elle a bien été enregistrée?


    person.r_idAddress me renvoie Null.


     


    Merci


  • Pourquoi les noms des valeurs qui ne marchent pas sont-elles entre guillemets, alors que le nom de celles qui marchent ne le sont pas ?


  • Pourquoi les noms des valeurs qui ne marchent pas sont-elles entre guillemets, alors que le nom de celles qui marchent ne le sont pas ?




    Simple coà¯ncidence ;) c'est juste la console d'xcode qui met des guillemets autour des mots contenants un espace un - ou un _


  • Simple coà¯ncidence ;) c'est juste la console d'xcode qui met des guillemets autour des mots contenants un espace un - ou un _




     


    Ah. OK. Je me disais qu'il pouvait y avoir du KVC un peu louche la dessous.

  • AliGatorAliGator Membre, Modérateur
    Et tu les as remplies au moins tes relationships quand tu as rempli ta base avec les données ? Tu as indiqué que la Person *p1 et l'Address *a1 étaient liées entre elles ? Pour qu'ensuite quand tu lui redemandes il retrouve l'adresse associée à  la personne via cette relationship ?
    (Ou bien tu t'es imaginé que ça se faisait tout seul, ou via un champ type clé étrangère que tu aurais créé toi-même confondant CoreData avec une BDD)
  • Aaah... non je pensais que c'était géré par Core Data via les primary keys.  :*


    Et c'est donc juste avant la sauvegarde que je relie les données entre-elles?


    Tu peux me montrer grossièrement un exemple?


     


    Merci de votre aide

  • jpimbertjpimbert Membre
    juillet 2013 modifié #13

    person.r_idAddress = address;

    Mais le nom r_idAddress me paraà®t un peu louche. ça ne ressemble pas à  un nom d'entité CoreData.


  • Non "r_idAddress" c'est ma relation en fait.


    J'vais essayer ça...


     


    Merci


  • AliGatorAliGator Membre, Modérateur
    CoreData est un système de gestion de Modèle de Données, orienté objet. C'est un peu différent d'une base de données : certes il y a énormément de choses similaires, et en pratique sous le capot les données sont stockés dans une base de données sqlite, mais au niveau des concepts, il y a quelques petites subtilités du fait que c'est vraiment un truc pensé "Objet" et pas "Base de Données" à  la base. Par exemple :
    - Pas besoin de déclarer une "Primary Key" toi-même (à  la limite CoreData doit en gérer une tout seul comme un grand sous le capot, mais en pratique tu t'en fous)
    - On ne parle pas de tables et de rangées, mais d'entités (NSEntity) et d'instances ou objets managés (NSManagedObjects). On ne parle pas de clés primaires et de clés étrangères, mais de relations, car dans CoreData tu indiques directement des Relationships entre des entités, alors que dans une BDD tu as besoin de te créer et gérer toi-même des clés primaires et étrangères pour implémenter ce concept de relation
    - Du coup d'ailleurs, dans CoreData si tu veux une relation many-to-many, bah tu exprimes une relation many-to-many, et c'est tout (concrètement tu exprimes qu'il y a une relation to-many entre A et B, et une relation to-many entre B et A), et c'est CoreData qui s'arrange du reste. Alors que dans une BDD en général tu es obligé de gérer ça toi-même, créer même une table intermédiaire pour stocker les relations entre les clés étrangères des 2 tables à  relier, et tout... mais ça CoreData s'en débrouille et fait ça pour toi.

    Donc pour les relations dans CoreData, ce sont bien des relations toutes simples entre une entité et une autre entité, que tu décris. Comme une Personne a une Adresse (one-to-one). Ou un album de musique contient plusieurs pistes (one-to-many), etc. Exactement comme, en dehors de CoreData si tu créais des classes Objective-C classiques, tu aurais une "@property Address* r_address" dans ta classe "Person" (et certainement une "@property Person* r_person" dans ta classe "Address" pour avoir la relation inverse). D'ailleurs concrètement c'est comme ça que CoreData te le représente quand il génère les classes Objective-C correspondant à  tes entités (NSEntity) CoreData. Il faut que tu fasses abstraction de l'aspect "Base de Données" et de l'aspect "besoin de gérer les relations soi-même et de créer des clés primaires et étrangères, voire de créer des tables intermédiaires, pour gérer les relations avec des jointures après", non, avec CoreData tout cela est transparent.
  • Yes bien compris et ça fonctionne autant pour les relations one-to-one que pour les relations one-to-many!!


    D'une pierre deux coups car effectivement maintenant que j'ai relié mes objets, je peux également "deleter" tous mes objets en cascade ( cf. autre post).


     


    Un grand MERCI à  vous  :D


Connectez-vous ou Inscrivez-vous pour répondre.