[Core Data] Probleme mise a jour entity dans relation parent/enfant

Lio70

Membre expert
Club iGen
16 Janvier 2004
2 396
1 282
Bonjour,

Soit le data model suivant, pour schématiser: 2 entities en relation parent/enfant "to-many" dans une base de données SQLite gérée avec Core Data. Les entités contiennent des attributs de type NSDecimalNumber.

L'entité enfant s'appelle Ordercontent et contient les attributs suivants:
- childValue1
- childValue2
- childTotal (egal a 'childValue1' multiplie par 'childValue2')
- une relation appelee ‘order’ vers le parent

L'entite parent s'appelle Order et contient l'attribut suivant:
- parentTotal (egal a la somme des childTotal des enfants)
- une relation appelee ‘content’ vers l’enfant

Quand on supprime un parent (objet Order), les enfants éventuels sont supprimes aussi, par suppression en cascade.

PROBLEME:
Quand on supprime un parent (peu importe qu'il contienne des enfants ou non), l'objet est supprime mais l'application se plante avec les messages suivants:

1. CoreData: warning: An NSManagedObjectContext delegate overrode fault handling behavior to silently delete the object with ID '0x80002b <x-coredata://7F7D281F-5381-49A2-80B3-CE08A250E752/Order/p2 <x-coredata://7F7D281F-5381-49A2-80B3-CE08A250E752/Order/p2>>' and substitute nil/0 for all property values instead of throwing.

2. CoreData: error: Mutating a managed object 0x80002b <x-coredata://7F7D281F-5381-49A2-80B3-CE08A250E752/Order/p2 <x-coredata://7F7D281F-5381-49A2-80B3-CE08A250E752/Order/p2>> (0x6080000c9f40) after it has been removed from its context.

Le premier message est du a un manque de gestion d’erreur dans le cas ou une certaine valeur est nil, mais la remediation a cela ne règle pas le problème dans son ensemble.

Deuxième -> Je ne vois pourtant pas, dans les classes ManagedObject, quel code tente de modifier l’objet après sa suppression.

Le problème de plantage disparait quand je retire du code tout ce qui concerne KVO (startObserving, stopObserving), méthodes qui furent nécessaires pour que la valeur parentTotal se mette a jour correctement en fonction des changements des enfants.

Sans l’attirail KVO, la valeur parentTotal n’est pas mise a jour lorsqu’on SUPPRIME un enfant. Par contre, elle est correctement mise a jour lorsqu’on AJOUTE ou qu’on MODIFIE un enfant.

A l’origine, le problème vient sans doute d’une mauvaise definition des getters et setters. En effet, ceux-ci ne sont pas définis complètement et la repercussion correcte des valeurs s’obtient surtout par appel a des fonctions contenant des ‘setValue_forKey’ par KVC dans le code de mes classes ManagedObject.

Avec Core Data, ceci n’est pas la meilleure façon de travailler. Je supprime donc tout ce qui est KVO, fonctions et KVC. Je suis en train de redéfinir correctement tous les getters et setters requis. J"ai termine pour l'entité enfant Ordercontent et ca marche très bien, mais pas encore fini avec le parent Order.

Certains d’entre vous auront peut-être une suggestion…
 
Bonjour,

le second problème ; il doit y avoir quelque chose qui iterate dans un autre processus ; c'est une erreur d'iterator qui est invalide ;

process 1 iterate:
process 2 remove entry:

process 1 while (list next) : { do } //
process 2 delete list[index]
process 1 iterator throws invalidating.

vous devriez attendre until-done, c'est une race condition, l'operation remove doit-être plus longue certainement O(log n), plus toutes les deallocations ou release count, reordering qui peuvent se passer en même temps.

Cordialement.
 
Dernière édition:
Merci Mboum de m'avoir mis sur la voie:

il doit y avoir quelque chose qui iterate dans un autre processus ; c'est une erreur d'iterator qui est invalide ;

process 1 iterate:
process 1 while (list next) : { do } //

Je viens de verifier la classe controller pour les actions faites sur la view ou sont gerees ces entites Order et Ordercontent.

Pour supprimer, j'override la methode remove par une IBAction de maniere a presenter un dialogue 'OK / Cancel' pour confirmer que je veux supprimer l'objet (eviter les suppressions accidentelles).

Bloc de code:
if (returnCode == NSAlertFirstButtonReturn) {
      [ordersController remove:nil];
      NSError *error = nil;
      [[self managedObjectContext] save:&error];
}

Le problème vient du fait que je veux sauver a ce moment plutôt que laisser Core Data gérer son graphe d’objets et sauver automatiquement quand l’application termine. Je sauve pour être sur que la base de données soit dans un état correct avant de faire d’autres operations (print, export…).

Quand je désactive la méthode ci-dessous, il n’y a plus de plantage :

Bloc de code:
[[self managedObjectcontext] save:&error];

Il faudra que je revise toute mon app car il y a plusieurs choses que je force explicitement alors que Core Data est fait pour s’en occuper implicitement. C’est une app que j’ai commence a developper avec l’API Objective-c pour SQLite: sqlite3. Puis j’ai decide de convertir le projet en Core Data pour experimenter. Donc il y a collision entre lignes de code relatives a deux manières de faire la meme chose. J’avoue que c’est un manque de confiance en la technologie. C’est comme les boites de vitesse automatiques dans les voitures. Je préfère le bon vieux shift stick, au moins c’est moi qui contrôle la voiture et non l’inverse.

Jadis, un certain pseudo sur ce forum aurait dit: :D
C'est du bangalore-style fini au pipi d'ane moisi !

Donc je vais nettoyer et optimiser pour Core Data, et finir de configurer correctement mes accesseurs dans les classes managedObject, Je reposterai ici en cas de problème.
 
  • J’aime
Réactions: Mboum
En joue... Feu !
C'est ennuyeux; un technicien de surface a fait son ouvrage et nous empeche de publier en ligne notre guide de maintien moral. Nous qui ne demandons qu'a aider notre prochain en l'amenant a l'etat d'eveil spirituel comme le Bouddha. D'autant que les missives a votre attention trouvent boite close sur ce systeme et que nous ne pouvons des lors partager des biscuits autour d'un the. Avez-vous prevu un bouton by-pass ?