web-dev-qa-db-ja.com

すべてのコアデータリレーションシップにはインバースが必要ですか?

SocialAppSocialAppTypeの2つのEntityクラスがあるとします。

SocialAppには、1つの属性:appURLと1つの関係:typeがあります。

SocialAppTypeには、baseURLnamefaviconの3つの属性があります。

SocialApp関係の宛先typeは、SocialAppTypeの単一レコードです。

たとえば、複数のFlickrアカウントの場合、多数のSocialAppレコードが存在し、各レコードには個人のアカウントへのリンクが保持されます。 「Flickr」タイプには、すべてのSocialAppTypeレコードが指すSocialAppレコードが1つあります。

このスキーマを使用してアプリケーションをビルドすると、SocialAppTypeSocialAppの間に逆の関係がないという警告が表示されます。

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

逆を必要とするのはなぜですか?

147
Alex Reynolds

実際には、逆を持たないためにデータの損失はありませんでした-少なくとも私は知っています。簡単なGoogleはあなたがそれらを使用する必要があることを示唆しています:

逆関係は物事を整頓するだけでなく、データの整合性を維持するために実際にコアデータによって使用されます。

- ココア開発セントラル

通常、両方向の関係をモデル化し、逆関係を適切に指定する必要があります。 Core Dataは、この情報を使用して、変更が行われた場合にオブジェクトグラフの一貫性を確保します(「関係とオブジェクトグラフの整合性の操作」を参照)。双方向の関係をモデル化しない理由の一部と、そうしない場合に発生する可能性のある問題については、「一方向の関係」を参照してください。

- コアデータプログラミングガイド

113

Appleのドキュメントには、逆の関係がないことで問題が発生する可能性がある状況を示唆する素晴らしい例があります。このケースにマッピングしましょう。

次のようにモデル化したと仮定します。 enter image description here

SocialAppからSocialAppTypeまでの "type"と呼ばれるto-one関係があることに注意してください。関係はnon-optionalで、"deny" delete ruleがあります。

次のことを考慮してください。

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

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

関係はオプションではないが、削除規則を拒否として設定しているため、このコンテキスト保存に失敗することが予想されます。

ただし、ここで保存は成功します。

その理由は、逆関係を設定していないからです。そのため、appTypeが削除されても、socialAppインスタンスは変更済みとしてマークされません。したがって、保存する前にsocialAppの検証は行われません(変更が発生していないため、検証は不要であると想定されます)。しかし、実際には変化が起こりました。しかし、それは反映されません。

AppTypeをリコールする場合

SocialAppType *appType = [socialApp socialAppType];

appTypeはnilです。

変だよね?オプションではない属性に対してnilを取得しますか?

したがって、逆の関係を設定していれば問題はありません。それ以外の場合は、次のようにコードを記述して、検証を強制する必要があります。

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];
130
MadNik

Dave MarkとJeff LeMarcheによるMore iPhone 3 Developmentで見つけた決定的な答えを言い換えます。

通常、アプリで逆関係を使用しない場合でも、常に逆を作成して指定することをお勧めします。このため、逆の指定に失敗すると警告が表示されます。

逆の関係がパフォーマンスを損なう可能性のあるシナリオがいくつかあるため、関係は逆にする必要はありません。たとえば、逆関係に非常に多くのオブジェクトが含まれているとします。インバースを削除するには、インバースを表すセットを反復処理する必要があり、パフォーマンスが低下します。

しかし、特別な理由がない限り、逆をモデル化します。 Core Dataがデータの整合性を確保するのに役立ちます。パフォーマンスの問題が発生した場合、後で逆の関係を比較的簡単に削除できます。

46
Rose Perrone

より良い質問は、「理由がありますnotが逆になりますか?」コアデータは、実際にはオブジェクトグラフ管理フレームワークであり、永続化フレームワークではありません。言い換えると、その目的は、オブジェクトグラフ内のオブジェクト間の関係を管理することです。逆関係により、これがmuchを容易にします。そのため、Core Dataは逆関係を想定しており、そのユースケース向けに記述されています。それらがなければ、オブジェクトグラフの一貫性を自分で管理する必要があります。特に、逆関係のない多対多の関係は、非常に動作を維持するのが難しい場合を除き、コアデータによって破損する可能性が非常に高くなります。逆関係のディスクサイズの面でのコストは、実際に得られるメリットと比較して、わずかなものです。

24
Barry Wark

少なくとも1つのシナリオがあります。これは、2つのオブジェクト間に別のコアデータ関係が既に存在し、オブジェクトグラフの維持を処理する場合に、インバースなしでコアデータ関係に適切なケースを作成できます。

たとえば、本には多くのページが含まれていますが、ページは1つの本に含まれています。これは、双方向の多対1の関係です。ページを削除すると関係が無効になりますが、ブックを削除するとページも削除されます。

ただし、書籍ごとに現在読んでいるページを追跡することもできます。これは、 "currentPage" property on Pageで実行できますが、その場合、ブック内の1ページのみが現在のページとしてマークされるように他のロジックが必要です。時間。代わりに、currentPage relationshipをBookから単一のページにすると、マークされている現在のページが常に1つだけになり、さらにこのページは単にbookで本を参照して簡単にアクセスできるようになります。現在のページ。

Graphical presentation of core data relationship between books and pages

この場合、相互関係はどうなりますか?主に無意味な何か。 「myBook」などを別の方向に戻すこともできますが、ページの「book」関係にすでに含まれている情報のみが含まれているため、独自のリスクが生じます。おそらく将来、これらの関係の1つを使用する方法が変更され、コアデータ構成が変更される可能性があります。 page.bookをコードで使用する必要がある場所でpage.myBookを使用した場合、問題が発生する可能性があります。これを予防的に回避する別の方法は、ページへのアクセスに使用されるNSManagedObjectサブクラスでmyBookを公開しないことです。しかし、そもそも逆をモデル化しない方が簡単であると言えます。

概説した例では、「無効化」との相互関係がないため、currentPage関係の削除規則を「アクションなし」または「カスケード」に設定する必要があります。 (Cascadeは、読みながら本のすべてのページをリッピングしていることを意味しますが、特に寒くて燃料が必要な場合はそうかもしれません。)

この例のように、オブジェクトグラフの整合性が危険にさらされておらず、コードの複雑さと保守性が改善されていることが実証できる場合、逆のない関係が正しい決定であると主張できます。

20
Duncan Babbage

ドキュメントにはインバースが必要ではないようですが、インバースを持たないことで実際に「データ損失」を引き起こすシナリオを解決しました。レポート可能なオブジェクトに多対多の関係を持つレポートオブジェクトがあります。逆関係がなければ、多対多関係への変更は再起動時に失われます。コアデータのデバッグを調べたところ、レポートオブジェクトを保存しているにもかかわらず、オブジェクトグラフ(関係)の更新が行われていないことが明らかになりました。私はそれを使用しませんが、逆に追加しました。そのため、必須とは言えないかもしれませんが、インバースのない関係には間違いなく奇妙な副作用があります。

4
greg

逆はObject Integrityにも使用されます(他の理由については、他の回答を参照してください)。

推奨されるアプローチは、両方向の関係をモデル化し、逆関係を適切に指定することです。 Core Dataは、この情報を使用して、変更が行われた場合にオブジェクトグラフの一貫性を確保します

From: https://developer.Apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/HowManagedObjectsarerelated.html#//Apple_ref/doc/uid/TP40001075-CH17-SW1

提供されたリンクは、inverseセットが必要な理由を示しています。これがないと、データ/整合性が失われる可能性があります。また、nilであるオブジェクトにアクセスする可能性が高くなります。

0
J. Doe