tentative illégale d'établir une relation « xyz » entre les objets dans des contextes différents
-
20-09-2019 - |
Question
J'utilise l'exemple d'application CoreDataBooks
d'Apple comme base pour tirer des données dans un contexte d'objet géré secondaire en arrière-plan, puis la fusion que les données dans le contexte de l'objet principal géré.
Les données que je suis dans tirais est une entité Book
avec à une relation avec une entité Owner
(appelée « propriétaire »). L'entité Owner
a à plusieurs avec les Book
(appelés « livres »).
Mes données est un document XML de la forme:
<Owner>
<Name>alexpreynolds</Name>
<ID>123456</ID>
</Owner>
<Books>
<Book>Book One</Book>
<Book>Book Two</Book>
...
<Book>Book N</Book>
</Books>
Book One
par Book N
sont associés à une Owner
("alexpreynolds, 123456"
).
Je suis analyse cela en une instance de Owner
et une NSMutableSet
composée d'instances de Book
.
Lorsque je tente de sauver la première fois, il enregistre fin et les données fusionnées apparaît dans l'affichage du tableau.
Au deuxième exception toutefois, lorsque le contenu XML contient un nouveau livre, il ne fonctionne pas.
Voici ce qui se passe:
Je tente ensuite de charger dans un document XML qui contient une nouvelle Book
pas déjà dans le contexte de l'objet principal géré. Le nouveau Book
utilise le même Owner
que celle qui est associée à l'autre Book
s.
Je routines qui ramassent cette Owner
unique, objet géré (que je l'ai déjà dans mon contexte de l'objet principal géré) et le Book
unique qui est pas trouvé dans le MOC primaire.
De cela, je crée un nouvel objet Book
dans le secondaire MOC, et je mis sa relation « owner
» pour pointer vers le Owner
unique que je trouve dans le primaire MOC.
Quand je sauve, je reçois l'erreur suivante:
*** Terminating app due to uncaught
exception 'NSInvalidArgumentException',
reason: 'Illegal attempt to establish a
relationship 'owner' between objects in
different contexts
(source = <Book: 0x7803590>
(entity: Book; id: 0x7802ae0 <x-coredata:///
Book/t527F06B2-3EB5-47CF-9A29-985B0D3758862>
; data: {
creationDate = 2009-10-12 06:01:53 -0700;
name = nil;
nameInitial = nil;
operations = (
);
owner = nil;
type = 0;
}) ,
destination = <Owner: 0x78020a0> (entity:
Owner; id: 0x3a56f80 <x-coredata://043AF2F0-1AD0-
4078-A5E8-E9D7071D67D1/Owner/p1> ; data: {
books = "<relationship fault: 0x7801bf0 'books'>";
displayName = alexpreynolds;
ownerID = 123456;
}))'
Comment puis-je créer une nouvelle entité Book
dans le MOC secondaire, afin que je puisse encore l'associer à une Owner
préexistante dans le primaire MOC?
La solution
Vous ne pouvez pas avoir des relations entre les objets dans différents contextes d'objets gérés. Donc, une façon de se déplacer qui est d'amener l'objet dans le contexte de l'objet géré.
Par exemple:
NSManagedObject *book = // get a book in one MOC
NSManagedObject *owner = // get an owner in a different MOC
[[owner mutableSetValueForKey:@"books"] addObject:[owner.managedObjectContext objectWithID:[book objectID]]];
Alors qu'est-ce que vous faites est aller chercher en fait le Book
dans le même contexte d'objet géré avec owner
. Gardez à l'esprit, cependant, que seul cela est possible si book
a déjà été enregistré. Le contexte de l'objet géré va chercher l'objet dans le magasin persistant, il doit être d'abord enregistré.
Autres conseils
J'ai eu le même problème et cette phrase m'a aidé à résoudre l'erreur.
Vous ne pouvez pas avoir des relations entre les objets différents gérés contextes d'objet. Donc, une façon de se déplacer qui est d'apporter la objet dans le contexte de l'objet géré.
Voici mon code (je l'ai remplacé les variables pour le faire fonctionner pour vous):
// Have the owner object and get the managedObjectContext
Owner *owner = [[DataFunctions alloc] getCurrentOwner];
NSManagedObjectContext *context = [owner managedObjectContext];
// Create a book and use the manageObjectContext of owner
Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context];
[newQuote setValue: "Book Title" forKey:@"title"];
[newQuote setOwner:owner];
J'espère que cette aide:)
Ici, vous essayez d'établir une relation entre deux objets qui sont récupérés / créés avec un contexte différent. Les données de base ne vous permettra pas d'établir de telles relations. Pour ce faire, vous devriez chercher le deuxième objet (vous essayez de faire une relation avec) le contexte du premier objet avec objectID. Maintenant, vous devriez être en mesure d'établir une relation entre ces deux objets. Par exemple:
MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in
let user = User.MR_createEntityInContext(localContext)!
.....
.....
}) //here local context stores data on end of block itself
MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in
let address = Address.MR_createEntityInContext(localContext)!
.....
.....
let user = localContext.objectWithID(self.user!.objectID) as! User
user.address = address
})
Espérons que cela vous aidera!
Comme l'erreur dit, vous n'êtes pas autorisé à avoir une relation dans un noyau objet de données dont la valeur est à un autre objet tenu dans un contexte différent. Une façon de contourner cela est d'attendre jusqu'à ce que vous enregistrez le nouvel objet et fusionner de nouveau dans le contexte primaire, puis définissez la relation owner
selon le cas (puisque les deux objets sont maintenant dans le même contexte, il n'y a pas de problème avec ça) .
book *book = [mainContext ........] //Get book from default context
NSManagedObjectID *objectId = [book objectID];
Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship
Version Swift ...
context.insert(objectFromOtherContext)