ページ

2010年5月22日土曜日

CoreData - リレーションシップ(6) 削除ルール「アクションなし」「無効にする」の比較

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: CoreData - リレーションシップ(5) マスター・ディティールとカスケード削除

タグを削除して削除ルールの違いを見てみる。

(参考)モデル




削除コード:

-(void)deleteFirstTag
{
NSManagedObjectContext* moc = [self managedObjectContext];
// (1) fetch from BlogEntry
NSLog(@"----- executeFetchRequest ------------------------------------------");
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Tag"
  inManagedObjectContext:managedObjectContext]];
NSError* error = nil;
NSArray* tags = [moc executeFetchRequest:request error:&error];
[request release];
Tag* tag1 = [tags objectAtIndex:0];
NSLog(@"----- delete an tag ------------------------------------------");
[moc deleteObject:tag1];
[moc save:&error];
if (error) {
NSLog(@"DELETE ERROR: %@", error);
} else {
NSLog(@"DELETED: Tag");
}
}


タグの削除

(1) 削除ルール「無効にする」

まず Tag.entriesの削除ルールを「無効にする」にして、タグを1つ削除してみる。

[17042:10b] CoreData: sql: BEGIN EXCLUSIVE
[17042:10b] CoreData: sql: DELETE FROM Z_2TAGS WHERE Z_2ENTRIES = 2 AND Z_3TAGS = 1
[17042:10b] CoreData: sql: DELETE FROM Z_2TAGS WHERE Z_2ENTRIES = 1 AND Z_3TAGS = 1
[17042:10b] CoreData: sql: DELETE FROM ZTAG WHERE Z_PK = ? AND Z_OPT = ?
[17042:10b] CoreData: sql: UPDATE ZBLOGENTRY SET Z_OPT = ?  WHERE Z_PK = 2 AND Z_OPT = 2
[17042:10b] CoreData: sql: UPDATE ZBLOGENTRY SET Z_OPT = ?  WHERE Z_PK = 1 AND Z_OPT = 2
[17042:10b] CoreData: sql: COMMIT


該当タグおよび中間テーブルがきちんと削除されている。その他、UPDATE が出てる。ZBLOGENTRY.Z_OPT が更新されているようだ。Z_OPT が何を指しているか不明。


(2) 削除ルール「アクションなし」

次は「アクションなし」

[17091:10b] CoreData: sql: BEGIN EXCLUSIVE
[17091:10b] CoreData: sql: DELETE FROM ZTAG WHERE Z_PK = ? AND Z_OPT = ?
[17091:10b] CoreData: sql: COMMIT


あー、ZTAGしか削除されていない。中間テーブル(Z_2TAGS)内のレコードは残ったままだ。
sqlite> select * from ztag;
3|2|2|iPhone
3|3|2|Mac
sqlite> select * from z_2tags;
1|1
1|2
1|3
2|1
↑ 1|1 と 2|1 が残ったまま。これはまずい。



というわけで、基本的にはデフォルトの「無効にする」が望ましい。


コメントの削除

ついでにコメントの削除も同様にみておく(リレーションが若干異なるので)。


(1) 削除ルール「無効にする」
[17156:10b] CoreData: sql: BEGIN EXCLUSIVE
[17156:10b] CoreData: sql: DELETE FROM ZBLOGCOMMENT WHERE Z_PK = ? AND Z_OPT = ?
[17156:10b] CoreData: sql: UPDATE ZBLOGENTRY SET Z_OPT = ?  WHERE Z_PK = 1 AND Z_OPT = 2
[17156:10b] CoreData: sql: COMMIT

該当するコメントが削除され、ZBLOGENTRYの Z_OPT が更新された。


(2) 削除ルール「アクションなし」

[17172:10b] CoreData: sql: BEGIN EXCLUSIVE
[17172:10b] CoreData: sql: DELETE FROM ZBLOGCOMMENT WHERE Z_PK = ? AND Z_OPT = ?
[17172:10b] CoreData: sql: COMMIT


コメントの削除のみ。


結論
紆余曲折あったが、削除ルールはデフォルトの「無効にする」が良い。

Z_OPT の意味が不明だが、これまでの挙動を見る限り「アクションなし」では意図しない動作になるので、デフォルトの「無効にする」が無難なようだ。「アクションなし」で Warning が出るのはその辺りの挙動について注意が必要ということだろう。


ソース:
CoreDataRelationship at 2010-05-22 from xcatsan's SampleCode - GitHub