[RESOLU] Versioning CoreData : Un peu de mal ...
Mick
Membre
Bonjour à tous,
J'ai une appli Core Data qui marche bien. J'utilise cette appli, et j'ai une base de données relativement bien fournie et que je DOIS pouvoir utiliser. Mon Soucis : pour faire évoluer l'appli, je dois modifier le datamodel pour faire des choses propres. Mais si je le fais violemment, je n'ai plus accès à ma base. J'ai donc été voir du coté du coreData programming guide au chapitre Versionning. Mais franchement j'ai un peu de mal.
Est-ce que quelqu'un a déjà pratiqué le versioning avec CoreData et pourrait me faire part de son expérience ? j'ai du mal à démarrer en fait. Je ne sais pas par où commencer : je dois au lancement de l'appli, vérifier les metadonnées du dataModel et comparer par exemple à une string stockée dans les preférences. Si la base est ancienne, je dois alors .. Quoi faire ? Il faut que j'initialise un moc provisoire avec l'ancienne base, et après ? comment réécrire dans la nouvelle ?
Perdu...
J'ai une appli Core Data qui marche bien. J'utilise cette appli, et j'ai une base de données relativement bien fournie et que je DOIS pouvoir utiliser. Mon Soucis : pour faire évoluer l'appli, je dois modifier le datamodel pour faire des choses propres. Mais si je le fais violemment, je n'ai plus accès à ma base. J'ai donc été voir du coté du coreData programming guide au chapitre Versionning. Mais franchement j'ai un peu de mal.
Est-ce que quelqu'un a déjà pratiqué le versioning avec CoreData et pourrait me faire part de son expérience ? j'ai du mal à démarrer en fait. Je ne sais pas par où commencer : je dois au lancement de l'appli, vérifier les metadonnées du dataModel et comparer par exemple à une string stockée dans les preférences. Si la base est ancienne, je dois alors .. Quoi faire ? Il faut que j'initialise un moc provisoire avec l'ancienne base, et après ? comment réécrire dans la nouvelle ?
Perdu...
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
J'ai eu à faire une migration de base core data (format SQLITE). Les changements étaient minines (ajout de certains champs, changement de nom pour certains). Pour ma part voici ce que j'ai fait (sachant de mon expérience dans ce domaine n'est pas bien énorme):
- J'ai créer un seconde version de mon datamodel (avec les modifs de base) que j'ai ensuite positionné comme Datamodel à utiliser par défaut.
- Lors de l'ouverture du "persistant store", le NSDictionnary siuvant est passé en paramètre à la méthode "addPersistentStoreWithType"
- J'ai ensuite ajouté un fichier "mapping model" qui permet de donner à CoreData les informations nécessaire pour passer d'un modéle de données à un autre.
- A la première ouverture de la base de données CoreData à su gérer "tout seul" la migration vers la nouvelle base.
Toujours dans mon cas la base de données est relativement petite et sur iPhone. Mais je suppose que la méthode doit être similaire sur Mac OS X.
Voila.
Mais ta proposition concerne Leopard il me semble. (Il y a en effet des outils à partir de X.5 pour réaliser des migrations de dataModel). Mon soucis est que mon appli doit fonctionner sur Tiger, donc exit les outils de versioning...
J'ai commencé, tel que le préconise Apple, à utiliser des metaData pour indiquer un N° de version. J'arrive effectivement à récupérer la version qui a servi à construire le "store", et à agir en conséquence. J'en suis à la migration => il faut que je parcours une à une toutes mes entités, et que je les recréent dans le nouveau managedObjectContext, et il faut pouvoir mettre à jour toutes les relations... Bref, un gros "merdier" si je puis me permettre.
Si qq a une solution qui ne fait pas trop mal... aux doigts !
Ouais, c'est un gros guêpier, c'est bien pourquoi Apple s'est dépêchée d'ajouter les outils de migration de base dans 10.5.
As-tu vraiment besoin d'une compatibilité avec 10.4 ? ça devient vraiment très rare comme OS.
j'ai tenté d'installer leopard, mais au niveau performances cela n'avait rien à voir avec tiger. (démarrages longs, réactivité bof).
En tout cas, j'ai saisi le principe de la migration, mais la mise en oe“uvre avec une structure complexe me laisse perplexe. (voilà que je fais des rimes maintenant). En effet, j'avais commencé par lister toutes les entités (entityDescription), de les passer en revue une à une et de fetcher l'ensemble des managedObjects correspondant. Puis ensuite créer poour chaque un nouveau managedbject, et copier un à un les attributs. Mais c'était sans compter les relationships ! Il faut en effet avoir instancié les objets liés pour mettre à jour la relation n'est-ce pas ? a moins qu'il y ait une astuce avec les ID's ? (et encore, quand je crée les nouveaux objets dans le nouveau moc, ces objets se voient attribuer de nouveaux ID's qui n'ont a priori rien à voir avec les anciens)
Tel que le dirait un grand poète du XXIè : Now I'm lost, and I'm screaming for help....
Si le mac n'explose pas, j'aurai de la chance.
Et ce n'est que le début...
(Je précise car je suis tombé dans ce piège autrefois).
Je vais tenter une autre approche : parcourir les entités une à une, et ne pas m'occuper des relations dans un premier temps, mais créer un dictionnaire de "mapping" d'ID => Les clefs sont les objectID anciens, et les valeurs sont les objectID nouveaux. Ainsi, j'ai une table de correspondance entre les anciens ID et les nouveaux.
Du coup, je réitère une deuxième fois le parcours des entités une à une afin de mettre à jour les relations. Normalement tous les objets existent déjà lors de cette deuxième passe. Cela va m'éviter de faire des boucles imbriquées les unes dans les autres (illisible et dangereux car possibilité de boucle infinie...)
Je vous tiens au courant (pour ce que cela intéresse !)
Ayant toujours pour habitude de coder des fonctions d'export et d'import de mes tables sous divers format (SQLlite me fait un peu peur de part sa faible lisibilité/récupérabilité en cas de crash ...) je me contentais alors d'exporter toutes mes tables une à une indépendamment et de coder la nouvelle fonction d'import pour le nouveau modèle pour créer les MObjects et rétablir les liens (One to One ou many to One) à partir de l'ID.
Ca marchait impeccable même avec de grosses tables de plus de 50 000 MObjects.
Lors de la deuxième itération pour mettre à jour les relationShips, j'obtiens nil pour certains ID ! Je ne vois pas comment c'est possible... Si qq voit un problème..
Dans mon parcours des entités, lorsque la base est en sqlite, et bien il y a des entités zappées lors de la création du mapID.
J'ai converti en xml, et refait la manip, et là pas de problèmes !
Va comprendre !
Mais sachant qu'un MObjectID n'est véritablement attribuée qu'au moment de sa première sauvegarde.
Sachant qu'une base SQLLite n'est pas sauvegardée à chaque action.
On peut se demander s'il ne faudrait pas forcer cette sauvegarde avant de récupérer l'ID.
Le hic, pas des moindre, c'est que dans ce cas tu devrais au moins avoir une ID transitoire (d'avant première sauvegarde) et non pas nil ... mais ça reste une piste à explorer peut-être ?
Sur iPhone, et ce d'ailleurs quelle que soit l'application, si tu veux scroller dans une zone scrollable qui est elle-même dans une autre zone scrollable " par exemple scroller dans un bloc de code dans le forum, bloc qui est dans une page elle-même scrollable " il suffit de scroller non pas avec un seul doigt (ce qui fait scroller la page) mais avec deux doigts (ce qui la fera scroller la zone scrollable "du niveau inférieur")
C'était l'astuce du soir, à vous les studios !
Les entités "de base" sont bien présentes, mais les relations sont "corrompues". Je ne comprends pas pourquoi.
Peut-être que c'est à cause des ID provisoires ? j'avoue être un peu paumé.
Je vais tenter de ne mettre à jour QUE les to-one, et laisser core data gérer les to-many via les inverseRelationships pour voir si c'est pas ça le bug. (en effet, j'ai respecté le pattern base de donnée relationnelle, chez moi, many-to-many ça n'existe pas...)
Je vous tiens au courant.
J'avais stupidement mis à jour les anciens objets au lieu des nouveaux ! Vraiment un boulet quand je m'y mets.
Si des gens sont intéressé par ma méthode de mise à jour je peux envoyer mon code.
Ohoooo, merci Ali
J'ai la vague impression d'avoir déjà fait ainsi y'a pas si longtemps mais j'avais complètement oublié jusqu'à l'existence d'une possibilité.