Remplacer un NSManagedObject par un autre
colas_
Membre
Bonjour,
J'ai dans mes données un objet X. Je souhaite le remplacer partout où il apparaà®t par un autre Y.
Autrement dit, dans le "graphe de NSManagedObject", avec dedans un objet X donné, je souhaite remplacer cet objet par un autre objet Y (de la même entité, évidemment).
Avant de me lancer dans un code un peu bourrin, du type : parcourir l'arbre et remplacer l'objet quand on tombe dessus, je voulais savoir si vous étiez déjà tombé sur cette problématique.
Merci !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si pour l'objet Menu (gastronomique) tu dois changer de dessert, le plus simple à mon avis serait de :
1- Faire un fetch de tous les menus ayant en relation le dessert X.
2- Pour tous les menus récupérés, appliquer le nouveau dessert Y en faisant un save régulier (et non pas d'un seul coup) pour gagner en performance.
Faire ça en background.
@Kuber :
Le problème c'est que le Dessert en question peut apparaà®tre :
- dans les Menu
- dans les Commande
- dans les Stock
De plus, si mon modèle évolue, ma fonction de rechercher/remplacer ne marchera plus si Dessert apparaà®t dans une nouvelle Entité.
Mais merci pour ta réponse, peut-être (sûrement) qu'il y a moyen de retrouver toutes les Entités qui se réfèrent au Dessert !
Si Menu à une relationship vers Dessert alors j'espère que tu as mis une relation inverse de Dessert vers menu (cet fortement conseillé !) du coup en partant du Dessert tu peux trouver facilement tous les menus qui le contiennent, y'a pas de code à rajouter juste à boucler sur ta relation.
@Ali : très bonne idée, merci !
Attention à la levée des faults (accès aux relationships) qui risque de grever les performances (selon le volume de données). Il faudrait - si j'ai bien compris ta proposition - faire un fetch sur Dessert. Du coup, un prefetching sur les relations (du genre menus, commandes, stocks).
En fait, si son modèle évolue, il faudra modifier le fetch. À mon sens, dans tous les cas, une modif du modèle nécessitera une modif de sa fonction rechercher/remplacer. Ce qu'il veut éviter apparement.
@Kuber :
à l'aide de NSRelationshipDescription et en particulier de la property inverseRelationship, on doit peut-être pouvoir rendre le parcours des relations automatiques.
Que va m'apporte le prefetching ? Un seul gros accès au contexte plutôt que plein de petits accès ?
Quand tu fais un fetch sur une entité, core data ne met pas en mémoire les relations ; elles sont en fault. Du coup, à chaque fois qu'on accède à une relation, Core Data va lever le fault (accès disque) pour ramener en mémoire l'objet correspondant. Ca coûte cher.
Le prefetching permet d'éviter dans une certaine mesure ces accès incessants et de gagner en performance.
C'est une chose à penser...
Mais bon, pour l'optimisation faut tester différentes choses avec Core Data.
Quant au préfetching, il faut trouver l'équilibre.
- Le faulting (connu aussi sous le nom de "futures") est un mécanisme qui permet d'éviter de se ramener toute la pelote de laine (si tu demandes un Dessert qu'il ne ramène pas automatiquement tous les objets liés à Dessert alors que potentiellement tu n'en auras pas besoin, et encore moins les objets liés à ces objets liés, et les objets liés à ceux-là , etc... bref éviter de ramener tout le graphe au final). Donc c'est une bonne chose pour éviter des jointures inutiles dans la base et de te ramener un gros paquet de données inutiles.
Mais d'un autre côté si tu sais que tu vas avoir besoin de ces relations, pour éviter de faire une requête pour avoir ton Dessert, puis une autre pour les Menus associés à ce Dessert, et encore une autre pour les Commandes associées, etc... alors qu'avec une seule requête (avec jointure) dès le début, ça te ramène tout d'un coup et c'est plus efficace. Certes du coup ça te tire un peu + de données, mais en même temps tu sais que tu vas en avoir besoin.
Bref, faut trouver l'équilibre entre ramener ce qu'il te faut pas pas non plus tout l'arbre car là non plus les performances ne seront pas idéales si tu fais une requête qui doit te ramener + que ce qu'il te faut.
Voilà ce que j'ai codé (méthode pour remplacer un objet par un autre dans un graphe CoreData)
Le .h
Le .m