166 votes

Chaque relation de données de base doit-elle avoir une inverse?

Disons que j'ai deux classes d'Entité: SocialApp et SocialAppType

En SocialApp j'ai un Attribut: appURL et une Relation: type.

En SocialAppType j'ai trois Attributs: baseURL, name et favicon.

La destination de l' SocialApp relations type est un enregistrement unique en SocialAppType.

Par exemple, pour de multiples comptes Flickr, il y aurait un certain nombre de SocialApp des enregistrements, chaque enregistrement de la tenue d'un lien vers le compte d'une personne. Il y aurait un SocialAppType record pour le "Flickr" type, que tous SocialApp dossiers.

Quand j'ai créer une application avec ce schéma, je reçois un avertissement qu'il n'y a pas de relation inverse entre l' SocialAppType et SocialApp.

 /Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse

Ai-je besoin d'un inverse, et pourquoi?

153voto

MadNik Points 1131

La documentation d'Apple est un excellent exemple qui suggèrent une situation où vous pourriez avoir des problèmes à ne pas avoir de relation inverse. Permet à la carte dans ce cas.

Supposons que vous modélisé comme suit enter image description here

Remarque vous avez à une relation appelée "type", à partir de SocialApp à SocialAppType. La relation est non-facultatif et a un "refuser" la suppression de la règle.

Maintenant Permet d'envisager la suite de Code.

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];
BOOL saved = [managedObjectContext save:&error];

Ce que nous attendons est l'échec de ce contexte enregistrer depuis que nous avons mis la suppression de la règle de Nier alors que la relation est non facultatif.

Mais ici, l'enregistrer réussit.

La raison est que nous n'avons pas défini une relation inverse. En raison de cette socialApp instance obtenez pas marqué comme modifié lorsque appType est supprimé. Donc pas de validation qui se passe pour socialApp avant de les enregistrer (Il n'assume aucune validation nécessaire, car aucune modification n'est intervenue). Mais en réalité, un changement s'est produit. Mais il n'est pas pris en compte.

si nous nous rappelons appType par

SocialAppType *appType = [socialApp socialAppType];

appType est nul.

Tellement bizarre n'est-ce pas. obtenir nulle pour les non attribut facultatif?

Si vous n'êtes pas en difficulté, si vous avez mis en place la relation inverse. Sinon, vous avez à faire forcer la validation par l'écriture de code comme suit.

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];

[socialApp setValue:nil forKey:@"socialAppType"]
BOOL saved = [managedObjectContext save:&error];

124voto

Matthew Schinckel Points 15596

Dans la pratique, je n'ai pas eu de perte de données due à ne pas avoir un inverse - au moins à ce que je sache. Un rapide Google suggère que vous devriez utiliser:

Une relation inverse n'est pas juste rendre les choses plus bien rangé, c'est en fait utilisé par la Base de Données pour gérer les données de l'intégrité.

-- Cacao Dev Centrale

Vous devez généralement modèle les relations dans les deux directions, et spécifiez l'inverse des relations de façon appropriée. Base de Données utilise cette informations pour assurer la cohérence de l'objet graphique si un changement est (voir "la Manipulation de Relations et de l'Objet Graphique de l'Intégrité"). Pour un discussion de certaines des raisons pour lesquelles vous voulez peut être pas un modèle relation dans les deux sens, et certains des problèmes qui pourraient survenir si vous n'avez pas le cas, voir "Unidirectionnel Relations."

-- Base De Données Guide De Programmation

49voto

Rose Perrone Points 14478

Je vais paraphraser la réponse définitive, j'ai trouvé en Plus de l'iPhone 3 de Développement par Dave Marque et Jeff LeMarche.

Apple recommande généralement de toujours créer et spécifier l'inverse, même si vous n'utilisez pas la relation inverse dans votre application. Pour cette raison, il vous avertit lorsque vous ne fournissez pas l'inverse.

Les relations ne sont pas tenus d'avoir un inverse, parce qu'il y a quelques scénarios dans lesquels la relation inverse pourrait nuire à la performance. Par exemple, supposons que la relation inverse contient un très grand nombre d'objets. Retrait de l'inverse nécessite une itération sur l'ensemble que représente l'inverse, l'affaiblissement de la performance.

Mais , sauf si vous avez une raison particulière de ne pas, modèle de l'inverse. Il aide de Base de Données assurer l'intégrité des données. Si vous rencontrez des problèmes de performances, il est relativement facile de supprimer la relation inverse plus tard.

25voto

Barry Wark Points 73462

La meilleure question est, "est-il une raison de ne pas avoir un inverse"? L'essentiel des Données est vraiment un objet graphique cadre de gestion, pas une persistance cadre. En d'autres termes, son travail consiste à gérer les relations entre les objets dans l'objet graphique. Inverse les relations que ce beaucoup plus facile. Pour cette raison, la Base de Données s'attend inverse relations et est écrit pour ce cas d'utilisation. Sans eux, vous aurez à gérer l'objet graphique de la cohérence de vous-même. En particulier, à de nombreuses relations, sans une relation inverse sont très susceptibles d'être endommagés par des Données de Base à moins de travailler très dur pour garder les choses de travail. Le coût en termes de taille de disque de l'inverse des relations est vraiment peu par rapport à la prestation, il vous gagne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X