objective-c 每个核心数据关系都必须有反向关系吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/764125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does every Core Data Relationship have to have an Inverse?
提问by Alex Reynolds
Let's say I have two Entity classes: SocialAppand SocialAppType
假设我有两个实体类:SocialApp和SocialAppType
In SocialAppI have one Attribute: appURLand one Relationship: type.
在SocialApp我有一个属性:appURL和一个关系:type。
In SocialAppTypeI have three Attributes: baseURL, nameand favicon.
在SocialAppType我有三个属性:baseURL,name和favicon.
The destination of the SocialApprelationship typeis a single record in SocialAppType.
SocialApp关系的目标type是 中的单个记录SocialAppType。
As an example, for multiple Flickr accounts, there would be a number of SocialApprecords, with each record holding a link to a person's account. There would be one SocialAppTyperecord for the "Flickr" type, that all SocialApprecords would point to.
例如,对于多个 Flickr 帐户,将有许多SocialApp记录,每个记录都包含一个指向一个人帐户的链接。SocialAppType“Flickr”类型将有一个记录,所有SocialApp记录都将指向该记录。
When I build an application with this schema, I get a warning that there is no inverse relationship between SocialAppTypeand SocialApp.
当我使用此架构构建应用程序时,我收到一条警告,指出SocialAppType和之间没有反向关系SocialApp。
/Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse
Do I need an inverse, and why?
我需要一个逆,为什么?
采纳答案by Matthew Schinckel
In practice, I haven't had any data loss due to not having an inverse - at least that I am aware of. A quick Google suggests you should use them:
在实践中,我没有因为没有逆而丢失任何数据 - 至少我知道。快速谷歌建议你应该使用它们:
An inverse relationship doesn't just make things more tidy, it's actually used by Core Data to maintain data integrity.
逆向关系不仅使事情更整洁,它实际上被 Core Data 用来维护数据完整性。
--可可开发中心
You should typically model relationships in both directions, and specify the inverse relationships appropriately. Core Data uses this information to ensure the consistency of the object graph if a change is made (see “Manipulating Relationships and Object Graph Integrity”). For a discussion of some of the reasons why you might want to not model a relationship in both directions, and some of the problems that might arise if you don't, see “Unidirectional Relationships.”
您通常应该对两个方向的关系进行建模,并适当地指定反向关系。如果发生更改,Core Data 使用此信息来确保对象图的一致性(请参阅“操作关系和对象图完整性”)。有关您可能不想对双向关系建模的一些原因以及如果不这样做可能会出现的一些问题的讨论,请参阅“单向关系”。
-- Core Data Programming Guide
--核心数据编程指南
回答by MadNik
Apple documentation has an great example that suggest a situation where you might have problems by not having an inverse relationship. Let's map it into this case.
Apple 文档中有一个很好的示例,它表明您可能因没有反向关系而遇到问题。让我们把它映射到这个案例中。
Assume you modeled it as follows:

假设您按如下方式对其进行建模:

Note you have a to-onerelationship called "type", from SocialAppto SocialAppType. The relationship is non-optionaland has a "deny" delete rule.
请注意,您有一个称为“类型”的一对一关系,从到。该关系是非可选的,并且具有“拒绝”删除规则。SocialAppSocialAppType
Now consider the following:
现在考虑以下几点:
SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated
[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];
BOOL saved = [managedObjectContext save:&error];
What we expect is to fail this context save since we have set the delete rule as Deny while relationship is non optional.
我们期望此上下文保存失败,因为我们已将删除规则设置为拒绝,而关系是非可选的。
But here the save succeeds.
但在这里保存成功。
The reason is that we haven't set an inverse relationship. Because of that, the socialApp instance does not get marked as changed when appType is deleted. So no validation happens for socialApp before saving (it assumes no validation needed since no change happened). But actually a change happened. But it doesn't get reflected.
原因是我们没有设置反向关系。因此,当 appType 被删除时,socialApp 实例不会被标记为已更改。所以在保存之前没有对 socialApp 进行验证(它假设不需要验证,因为没有发生任何变化)。但实际上发生了变化。但它没有得到反映。
If we recall appType by
如果我们通过以下方式回忆 appType
SocialAppType *appType = [socialApp socialAppType];
appType is nil.
appType 为零。
Weird, isn't it? We get nil for a non-optional attribute?
很奇怪,不是吗?对于非可选属性,我们得到 nil 吗?
So you are in no trouble if you have set up the inverse relationship. Otherwise you have to do force validation by writing the code as follows.
所以如果你已经建立了逆关系,你就没有问题。否则,您必须通过编写如下代码来进行强制验证。
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];
回答by Rose Perrone
I'll paraphrase the definitive answer I found in More iPhone 3 Developmentby Dave Mark and Jeff LeMarche.
我将转述我在Dave Mark 和 Jeff LeMarche 的More iPhone 3 Development 中找到的明确答案。
Apple generally recommends that you always create and specify the inverse, even if you don't use the inverse relationship in your app.For this reason, it warns you when you fail to provide an inverse.
Apple 通常建议您始终创建和指定逆关系,即使您不在应用中使用逆关系。出于这个原因,它会在您未能提供逆时向您发出警告。
Relationships are not requiredto have an inverse, because there are a few scenarios in which the inverse relationship could hurt performance. For example, suppose the inverse relationship contains an extremely large number of objects. Removing the inverse requires iterating over the set that represents the inverse, weakening performance.
关系不需要有反向关系,因为在某些情况下反向关系可能会影响性能。例如,假设反向关系包含非常多的对象。去除逆需要迭代表示逆的集合,削弱性能。
But unless you have a specific reason not to, model the inverse. It helps Core Data ensure data integrity. If you run into performance issues, it's relatively easy to remove the inverse relationship later.
但是,除非您有特定的理由不这样做,否则请对 inverse 进行建模。它帮助 Core Data 确保数据完整性。如果您遇到性能问题,稍后删除反向关系相对容易。
回答by Barry Wark
The better question is, "is there a reason notto have an inverse"? Core Data is really an object graph management framework, not a persistence framework. In other words, its job is to manage the relationships between objects in the object graph. Inverse relationships make this mucheasier. For that reason, Core Data expects inverse relationships and is written for that use case. Without them, you will have to manage the object graph consistency yourself. In particular, to-many relationships without an inverse relationship are very likely to be corrupted by Core Data unless you work veryhard to keep things working. The cost in terms of disk size for the inverse relationships really is insignificant in comparison to the benefit it gains you.
更好的问题是,“有没有理由没有逆”?Core Data 实际上是一个对象图管理框架,而不是一个持久化框架。换句话说,它的工作是管理对象图中对象之间的关系。反向关系使这更容易。出于这个原因,Core Data 期望反向关系并且是为该用例编写的。没有它们,您将不得不自己管理对象图的一致性。特别是,没有反向关系的多对多关系很可能被 Core Data 破坏,除非你非常努力地保持工作正常。与它为您带来的好处相比,反向关系的磁盘大小成本确实微不足道。
回答by Duncan Babbage
There is at least one scenario where a good case can be made for a core data relationship without an inverse: when there is another core data relationship between the two objects already, which will handle maintaining the object graph.
至少有一个场景可以为没有逆的核心数据关系提供一个很好的案例:当两个对象之间已经存在另一个核心数据关系时,它将处理维护对象图。
For instance, a book contains many pages, while a page is in one book. This is a two-way many-to-one relationship. Deleting a page just nullifies the relationship, whereas deleting a book will also delete the page.
例如,一本书包含许多页,而一页在一本书中。这是一种双向多对一的关系。删除页面只会使关系无效,而删除一本书也会删除页面。
However, you may also wish to track the current page being read for each book. This could be done with a "currentPage" propertyon Page, but then you need other logic to ensure that only one page in the book is marked as the current page at any time. Instead, making a currentPage relationshipfrom Book to a single page will ensure that there will always only be one current page marked, and furthermore that this page can be accessed easily with a reference to the book with simply book.currentPage.
但是,您可能还希望跟踪每本书正在阅读的当前页面。这可以通过Page上的“currentPage”属性来完成,但是您需要其他逻辑来确保在任何时候书中只有一页被标记为当前页面。相反,建立从 Book 到单个页面的 currentPage关系将确保始终只有一个当前页面被标记,而且这个页面可以通过简单的 book.currentPage 引用这本书来轻松访问。


What would the reciprocal relationship be in this case? Something largely nonsensical. "myBook" or similar could be added back in the other direction, but it contains only the information already contained in the "book" relationship for the page, and so creates its own risks. Perhaps in the future, the way you are using one of these relationships is changed, resulting in changes in your core data configuration. If page.myBook has been used in some places where page.book should have been used in the code, there could be problems. Another way to proactively avoid this would also be to not expose myBook in the NSManagedObject subclass that is used to access page. However, it can be argued that it is simpler to not model the inverse in the first place.
在这种情况下,互惠关系是什么?一些很大程度上是荒谬的。“myBook”或类似的东西可以在另一个方向添加回来,但它只包含页面的“book”关系中已经包含的信息,因此会产生它自己的风险。也许在未来,您使用这些关系之一的方式会发生变化,从而导致您的核心数据配置发生变化。如果在代码中应该使用 page.book 的某些地方使用了 page.myBook,则可能会出现问题。另一种主动避免这种情况的方法也是不在用于访问页面的 NSManagedObject 子类中公开 myBook。然而,可以说首先不对逆建模更简单。
In the example outlined, the delete rule for the currentPage relationship should be set to "No Action" or "Cascade", since there is no reciprocal relationship to "Nullify". (Cascade implies you are ripping every page out of the book as you read it, but that might be true if you're particularly cold and need fuel.)
在概述的示例中,currentPage 关系的删除规则应设置为“No Action”或“Cascade”,因为与“Nullify”没有相互关系。(Cascade 意味着你在阅读书中的每一页都被撕掉了,但如果你特别冷并且需要燃料,这可能是真的。)
When it can be demonstrated that object graph integrity is not at risk, as in this example, and code complexity and maintainability is improved, it can be argued that a relationship without an inverse may be the correct decision.
当可以证明对象图完整性没有风险时,如本例所示,并且代码复杂性和可维护性得到提高,可以认为没有逆的关系可能是正确的决定。
回答by greg
While the docs don't seem to require an inverse, I just resolved a scenario that did in fact result in "data loss" by not having an inverse. I have a report object that has a to-many relationship on reportable objects. Without the inverse relationship, any changes to the to-many relationship were lost upon relaunch. After inspecting the Core Data debug it was apparent that even though I was saving the report object, the updates to the object graph (relationships) were never being made. I added an inverse, even though I don't use it, and voila, it works. So it might not say it's required but relationships without inverses can definitely have strange side effects.
虽然文档似乎不需要反演,但我只是解决了一个实际上因没有反演而导致“数据丢失”的场景。我有一个报告对象,它在可报告对象上有一对多的关系。如果没有反向关系,重新启动时对多对关系的任何更改都会丢失。在检查 Core Data 调试后,很明显即使我保存了报告对象,也从未对对象图(关系)进行更新。我添加了一个逆,即使我不使用它,瞧,它的工作原理。所以它可能不会说它是必需的,但没有逆的关系肯定会产生奇怪的副作用。
回答by J. Doe
Inverses are also used for Object Integrity(for other reasons, see the other answers):
逆也用于Object Integrity(出于其他原因,请参阅其他答案):
The recommended approach is to model relationships in both directions and specify the inverse relationships appropriately. Core Data uses this information to ensure the consistency of the object graph if a change is made
推荐的方法是对两个方向的关系建模并适当地指定逆关系。如果发生更改,Core Data 使用此信息来确保对象图的一致性
来自:https: //developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/HowManagedObjectsarerelated.html#//apple_ref/doc/uid/TP40001075-CH17-SW1
The provided link gives you ideas why you should have an inverseset. Without it, you can lose data/integrety. Also, the chance that you access an object which is nilis more likely.
提供的链接为您提供了为什么应该拥有inverse一套的想法。没有它,您可能会丢失数据/完整性。此外,您访问对象的nil可能性更大。
回答by Dhilip
There is no need for inverse relationship generally. But there are few quirks/bugs in Core data where you need an inverse relationship. There are cases where relationships/objects go missing , even though there is no error while saving the context, if there are missing inverse relationship. Check this example, which I created to demonstrate objects missing and how to workaround, while working with Core data
一般不需要逆关系。但是在需要反向关系的核心数据中很少有怪癖/错误。如果缺少反向关系,即使保存上下文时没有错误,也会存在关系/对象丢失的情况。检查此示例,我创建该示例以演示在使用 Core 数据时丢失的对象以及如何解决

