3

対多関係に逆がない場合、コア データに問題があります。関連するプロパティに加えられた変更は保持されません。これは、グーグルで見つけることができるので、私たちの多くが直面している問題です。

これは、明らかな答えや逆の関係を追加する以外に、永続性を達成するためのトリック/回避策を見つけた人がいるかどうかを尋ねることです.

背景:

  • ドキュメントで一方向の関係が推奨されていなくても、禁止されているわけではありません。ドキュメントは、逆がない場合に発生する責任のみを主張しています。
  • 逆を必要としない理由は、core-data doc に概説されています。1 つのエンティティに多数のアイテムがリンクされている場合、アイテムが追加されるたびに、逆の関係により大きな NSSet が読み込まれます。メモリを消費しています。理由もなく許容量を超えている可能性があります。

従業員/部門の典型的なパラダイムでは、複数の部門に所属できる膨大な数の従業員がいる場合、従業員から部門への対多関係が必要です。従業員が部門にリンクされるたびに、(非常に) 大きい NSSet をロード、更新、および保存する必要があるため、逆は必要ありませんさらに、部門エンティティが削除されない場合、グラフの整合性を維持するのは簡単です。

これがコアデータの機能であり、逆の関係が必須であるという返信はしないでください。これは明記されておらず、機能というよりはバグのようなものです。バグ レポートを投稿しても、現在展開されているシステムのポイントは解決されません。

編集: Join エンティティ ソリューション この編集は、以下の Dan Shelly の回答提案をより明確にし、議論するためのものです。

まず、最初に返信するために、私は多対多ではなく、真の一方向対多を目指しています。リンクされたページとまったく同じページには、引用したものより少し下にこのテキストがあります。

一方向の関係

双方向の関係をモデル化することは厳密には必要ではありません。場合によっては、そうしない方が便利な場合があります。たとえば、対多リレーションシップに非常に多数の宛先オブジェクトがあり、リレーションシップをトラバースする可能性がほとんどない場合です (リレーションシップの宛先にある多数のオブジェクト)。ただし、双方向の関係をモデル化しないと、オブジェクト グラフの一貫性を確保し、変更を追跡し、元に戻す管理を行うために、多くの責任が課せられます。

つまり、結合エンティティを追加するという提案されたソリューションは、コアデータに自動的に生成および更新させるソリューションがない場合の方法です。

IMO、そして私のユースケースでは、結合エンティティは部門との関係を持つ必要さえありません。この一対一は役に立たず、関連する部門情報を保持する結合エンティティのプロパティ (objectID やそれに到達するための他のインデックス付きプロパティなど) に置き換えることができます。

例:
DepartmentEmployee:
プロパティ: Dept_ix (整数)
関係: 従業員 (to-one、nullify)

4

3 に答える 3

1

最初にあなたのコメントへの返信:

IMO、そして私のユースケースでは、結合エンティティは部門との関係を持つ必要さえありません。この一対一は役に立たず、関連する部門情報を保持する結合エンティティのプロパティ (objectID やそれに到達するための他のインデックス付きプロパティなど) に置き換えることができます。

これはまさに、結合されたリレーションシップで部門プロパティが行っていることです。
生成された SQLite 構造を見ると、Employee エンティティと Department エンティティの間に、int64ID のみを保持する追加のマッピング テーブルが表示されます。

さて、与えられた例は次のとおりです。

従業員/部門の典型的なパラダイムでは、複数の部門に所属できる膨大な数の従業員がいる場合、従業員から部門への対多関係が必要です。従業員が部門にリンクされるたびに、(非常に) 大きい NSSet をロード、更新、および保存する必要があるため、逆は必要ありません。さらに、部門エンティティが削除されない場合、グラフの整合性を維持するのは簡単です。逆のない単純な 1 対多の関係は、簡単に実装できます。
関係の「多」側にあるオブジェクトの別のプロパティとして見ることができます。

この例では、次の種類の 1 対多の関係を要求します:
従業員->> 部門 (従業員は多くの部門に属している場合があります)
逆は:
部門--> 従業員
多対多の関係を実装してはならないため逆がない場合は、フレームワークの実装に準拠していることを確認するためだけに、関係の対 1 側を実装する必要があります。

繰り返します:
ドキュメントにより、逆の関係が定義されていないと、多対多の関係は維持されないことがわかっています。
==>
逆を使わずに関係をモデル化するのが好きなので、カップリングの to-ONE 部分としてのみモデル化します (to-many としてモデル化すると、フレームワークによって約束された永続性に違反します)
。フォルダー内のファイルの定義 (ファイルは複数のフォルダーに属することはできません)、または親子関係。
==>
関係を次のように定義する必要があります:
Department-->Employee (従業員を 1 人しか収容できない部署は実際には部署ではないため、これはあまり意味がありません)

別の天使から見ると (否定的な証明):
フレームワークに逆らって、逆数のない多対多の関係を定義したいとします。
==>
それは、... 多対関係または ... 多対関係を残して一方向にのみ実装することを意味します
==>
これは同じことですよね (対多関係) from and entity1 to entity2)
==>ここで、1 対多
の関係があり、その逆を実装しないことを選択した場合、対多の部分を実装することを選択できますか? いいえ、できません。これは、多対多の関係の半分にすぎないように見えます ==>その 1 対 1 の部分
を実装する必要があります

もう少し理にかなっているように、より論理的なものを示します:
Department-->>Employee したがって、この 1 対多の関係の実装は次のようになります:
Department<--Employee

これにより、次の SQLite DB 構造が生成されます:
ZDEPARTMENT:
Z_PK
Z_ENT
Z_OPT
ZNAME

ZEMPLOYEE:
Z_PK
Z_ENT
Z_OPT
ZDEPARTMENT (int)
ZNAME

Department でフェッチされたプロパティを定義して、それに属するすべての従業員をフェッチできるようになりました
employeesdepartment == $FETCH_SOURCE

Departmentのメソッドでこの関係を強制できますprepareForDeletion(テストされていません):
(最初userInfoに Department にディクショナリを設定して、強制のタイプを保持します)
(「Deny」ルールの実装は読者に任せました :D )

- (void) prepareForDeletion
{
    [super prepareForDeletion];
    NSEntityDescription* entity = [self entity];
    NSDictionary* dict = [entity userInfo] ;
    if ([dict count]) {
        [dict enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL *stop) {
            NSArray* arr = [self valueForKey:key];
            if( [value isEqualToString:@"cascade"]) {
                for (NSManagedObject* obj in arr) {
                    [[self managedObjectContext] deleteObject:obj];
                }
            } else if ( [value isEqualToString:@"nullify"] ) {
                NSArray* arr = [self valueForKey:key];
                for (NSManagedObject* obj in arr) {
                    [obj setValue:nil forKey:@"department"];
                }

            }
        }];
    }
}

私が見る限り、これは逆の関係に関してあなたができるすべてです。それでも多対多の関係が必要だと思う場合は、私の他の回答を参照してください。

よろしく、
ダン。

于 2013-04-07T18:30:18.783 に答える
0

関係を完全に廃止し、従業員の外部キーをプログラムで管理することを検討しましたか?

既存の部門のリスト (選択リストなど) からプロパティを設定する UI がある場合は、単にそのリストから主キーを取得し、それをdepartmentID従業員のプロパティとして割り当てることができます。

次に、従業員と部門の間の参照整合性を維持するために、指定されたものが有効であること (つまり、フェッチされた部門のリストにあること) および/または null でないことvalidateDepartmentID:errorをチェックするメソッドを Employee オブジェクトに実装できる必要があります。departmentID

部門の従業員のリストを取得する場合、取得したプロパティを使用するかNSFetchedResultsController、部門の従業員リストを含む のインスタンスを返すインスタンス メソッドを部門に追加できます。

他に行う必要があるのは、Department クラス (おそらく on ) に削除ロジックを挿入して、影響を受ける子レコード-prepareForDeletionの を更新することだけです。departmentIDそれはあなたのビジネスロジックに依存します。

プロパティの検証に関するAppleのドキュメントは、それらに精通していない場合をカバー-prepareForDeletionしています。-validateValue:forKey:error

于 2013-04-07T22:54:11.817 に答える