1

(答えが見つかりました。以下を参照してください。)

次のコードでは、いくつかの関係をリンクして、約 350,000 レコードを更新しています。しかし、最終的に sqlite データベースを調べたところ、関係の一部しか保存されていませんでした。残りはまだゼロです。

-アップデート-

問題のコードを説明する前に、dictionaryOfSynsetDictionariesプリフェッチされたsynsetオブジェクトが含まれていることを説明する必要があります。これは、キーが「n」、「v」、「a」、および「r」(4 つの品詞または )である 4 つの辞書を含む辞書として編成されていますpos。各内部辞書にはsynset、NSManagedObject からサブクラス化されたオブジェクトへの参照が含まれています。

各内部辞書は、 と呼ばれるものによってキー付けされsynsetOffsetます。

SYNSET_POINTER以下のコードは、ストアからすべてのオブジェクトをフェッチし、それらを配列に入れます。各SYNSET_POINERオブジェクトは、および( ) プロパティsynsetによって参照されます。また、オブジェクトをby matchingおよび対応するin にリンクする関係も含まれています。synsetOffsetpartOfSpeechposSYNSET_POINTERsynsetsynsetOffsetpossynsetdictionaryOfSynsetDictionaries

オブジェクトをプリフェッチsynsetしてディクショナリに整理した後、次のコードはすべてのSYNSET_POINTERオブジェクトを配列にフェッチし、配列を反復処理して、synset ポインターをそれらの synset オブジェクトに対応する関係を介して直接リンクします。

ここに画像の説明を入力

SYNSET(上の図は、とオブジェクトの間の 2 つの関係を示していSYNSET_POINTERます。これは元のデータセット編成に基づいています。これらは 2 つの異なる目的を果たします。この質問では、1 対 1 の関係について言及しています。)

~更新終了~

更新を行うコードは次のとおりです。

[request setEntity:[NSEntityDescription entityForName:@"SYNSET_POINTER" inManagedObjectContext:[ManagedObjectContext moc]]];
predicate = nil;
[request setPredicate:predicate];
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"synsetOffset" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSArray *synsetPointersArray = [[ManagedObjectContext moc] executeFetchRequest:request error:&error];

int i = 0;
int j = 0;

for(SYNSET_POINTER *pointer in synsetPointersArray) {
    NSString *pos = pointer.partOfSpeech;
    NSString *offset = [pointer.synsetOffset stringValue];
    pointer.synsetPointer = [[dictionaryOfSynsetDictionaries objectForKey:pos] objectForKey:offset];
    error = nil;
    if (![[ManagedObjectContext moc] save:&error]) {
        NSLog(@"error with save\n%@\n%@",error.localizedFailureReason, error.localizedDescription);
        NSLog(@"pause and quit");
    }
    NSLog(@"pos %@, offset %@, pointer %@", pos, offset, pointer);
    if (j==100) {
        NSLog(@"%@ %d", pos, i);
        j=0;
    }
    i++;
    j++;
}

ここでは、synsetPointerNSManagedObject のサブクラスである SYNSET_POINTER クラスのポインターのプロパティを更新しています。synsetPointerこのデバッガ出力のように、ループの反復ごとに、リレーションシップが適切なオブジェクトを指していることがわかります。

2012-11-26 22:03:08.753           [26156:fb03] pos v, offset 5815, pointer <SYNSET_POINTER: 0x404e84f0> (entity: SYNSET_POINTER; id: 0x404d00d0 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET_POINTER/p282133> ; data: {
    partOfSpeech = v;
    pointerSymbol = "~";
    reverseRelatedSynset = "0x244cd880 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET/p85476>";
    sourceTarget = 0000;
    synsetOffset = 5815;
    synsetPointer = "0x244cdda0 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET/p83738>";
})
2012-11-26 22:03:08.822           [26156:fb03] pos v, offset 5815, pointer <SYNSET_POINTER: 0x404e8530> (entity: SYNSET_POINTER; id: 0x404d00e0 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET_POINTER/p285862> ; data: {
    partOfSpeech = v;
    pointerSymbol = "@";
    reverseRelatedSynset = "0x244cd870 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET/p86470>";
    sourceTarget = 0000;
    synsetOffset = 5815;
    synsetPointer = "0x244cdda0 <x-coredata://9136BC94-4D77-4DB6-B03F-4F3AA35E2E49/SYNSET/p83738>";
})

は値synsetPointersArrayでソートされsynsetOffsetます。Firefox の sqlite ビューアーでテーブルをソートできますが、ほとんどの値が nil のままであることがわかります。上記のデバッグ出力は、それらがすべて割り当てられていることを示しています。何らかの理由で、それらは保存されていません。

一部の更新を妨げるこのコードの問題を誰かが見ることができますか?

4

2 に答える 2

1

解決しました!

私が提供したすべての情報からは明らかではありませんでしたが、写真に示されている 1 対 1 の関係に問題があることがわかりました。

SYNSET_POINTER.synsetPointer は、ただ 1 つの SYNSET オブジェクトを指す必要があります。

しかし、複数の SYNSET_POINTER オブジェクトが個々の SYNSET オブジェクトを指している可能性があることがわかります

したがって、逆の関係である SYNSET.reverseSynsetPoint は、1 対多の双方向関係の一部として構成されている必要があります。

管理対象オブジェクトのコンテキストが逆の関係を解決するため、1 対 1 の関係は、以前に割り当てられたリンクが自動的に無効化されたことを意味します。SYNSET_POINTER と SYNSET の関係が既に設定されている SYNSET に新しい SYNSET_POINTER を割り当てると、SYNSET.reverseSynSetPointer が変更されるたびに既存のリンクが両方向で無効になります。これは SYNSET_POINTER 側にダングリング リンクを残しますが、管理対象オブジェクト コンテキストはそれを自動的に無効にします。

そのため、Core Data は設定と変更の保存を行っていました。しかし、これらのリンクの多くが構成された後、予想どおり、それらも無効化されていました。

私の場合、逆の関係は本当に必要なかったので、後で使用する可能性があると考えて、後付けとして含めました。私のアドバイスは、これらのタイプの逆の関係を最初に設定するときに慎重に検討することです。そうしないと、後で問題が発生する可能性があります。

于 2012-11-30T19:36:34.457 に答える
0

あなたのコードは非常に貧弱な変数名を使用しているため、何を達成したいのか理解するのが難しくなっています。ただし、基本的な概念上の誤りを犯しているようです。

一般に、コア データで関係を確立するために、他のコア データ オブジェクトへの参照をそれらのオブジェクトの属性として保存しません。むしろ、リレーションシップを使用して、コア データに外部キーの専門性を処理させます。リレーションシップにオブジェクトを追加するには、オブジェクト クラスで Core Data によって生成されたアクセサーを使用します。

Core Data Programming Guide の次のセクションを確認してください:
Relationships and Fetched Properties
Managed Objects

于 2012-11-27T10:40:44.350 に答える