(前回)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