ビルド時の Warning
例えば次のようなエンティティを定義してビルドすると..
Warningが出る。
Bidirectional(双方向)にするとこの Warningは消える。
Bidirectional が推奨される理由
ADC のリファレンスに書いてある。
Core Data Programming Guide: Relationships and Fetched Properties - Unidirectional Relationships
ここではそれぞれの方式によってオブジェクトグラフへの影響が説明されている。
- Bidirectional Relationships(双方向)にすると、オブジェクトグラフの整合性を保つことができる(オブジェクトへの変更をトラッキングする、アンドゥ管理)。
- Unidirectional Relationships(単方向)にすると、不整合が発生する場合がある。
Relationalship のルールとして、「非オプション(non-optional)」「削除禁止 (deny delete rule)」が設定されているものとする。
この時、下記のコードを実行したとする。
[employee setDepartment:department]; [managedObjectContext deleteObject:department]; BOOL saved = [managedObjectContext save:&error];すると成功する。通常だとルール違反により save: が失敗するはず。
理由は次の通り。
- Bidirectional Relationalship の場合、departmentを削除すると employee に変更マークがつけられる。その結果、save: 時にルール検証が行われ、エラーとなる。
- Unidirectional Relationships の場合 departmentを削除しても emploee に変更マークがつけられない。これは department側に employeeへの参照が無いため。その結果、 save: 時にルール検証が行われずエラーとならない。
当然不整合状態なのでこの後下記のコードを実行するとエラーとなる(※1)
id x = [employee department];
※1 Guideにはとある。具体的にどのようなエラーになるのかは未検証。
x will be a fault to "nowhere" rather than nil.
対策としては Bidirectional にするか、-[NSManagedObjectContext deleteObject:] の代わりに setValue:forKey: を使う。
[employee setValue:nil forKey:@"department"]
SQL
Bidirectional にした時に気になるのが発行されている SQL(※SQLite使用時)。関連先エンティティの情報が不要な時にも(JOINなどで)情報を持ってきていないか?
⇒ これは持ってきていない。
(参考)(旧) Cocoaの日々: CoreData - リレーションシップ(1) シンプルなモデル
基本的に関連先エンティティの情報は必要になったタイミングで SQLが発行される。
結論
Core Data のモデリングでは Bidirectional Relationships(双方向関連)を使う。
Responses
Leave a Response