3

DeviceAccount というモデルがあります。これは、多対多の関係を作成できる結合テーブルです。

参加するアカウントとデバイスを渡して、新しい DeviceAccount を作成する機能があります。ここを参照してください:

var createDeviceAccount = function (account, device) {
        var initialValues = {
            account: account,
            device: device
        };
        return manager.createEntity(entityNames.deviceAccount, initialValues);
    };

DeviceAccount を削除する機能があります。ここを参照してください:

var deleteDeviceAccount = function (account, device) {
        var baseQuery = entityQuery.from('DeviceAccounts');
        var p1 = new breeze.Predicate('device', 'eq', device);
        var p2 = new breeze.Predicate("account", "eq", account);
        var modQuery = baseQuery.where(p1.and(p2));
        var results = manager.executeQueryLocally(modQuery);
        results[0].entityAspect.setDeleted();
    };

同じデバイス/アカウントのペアをローカルで作成、削除、作成、削除しても問題はありません。サーバーに存在するデバイス/アカウントのペアを取得すると、問題なく削除できますが、再度追加すると、次のエラーが表示されます。

キャッチされないエラー: このキーは既にアタッチされています: DeviceAccount:#Test.Models-5:::5

これをさらに詳しく調べると、ローカル デバイスを削除すると entityState が「Detached」に変更され、サーバーにも存在するデバイスを削除すると、entityState が「Deleted」に変更されることがわかります。私はこれ以上先を追うことはできず、誰かがなぜこれが起こっているのか説明できることを望んでいましたか?

4

2 に答える 2

4

明確にするために、entityAspect.setDeleted を介してエンティティを削除すると、entityState が「削除済み」に設定されます。このアクションにより、次回の保存時に削除するエンティティがマークされ、クライアントのナビゲーション コレクションからも削除されます。エンティティは、この操作の後も EntityManager によって追跡されています。

対照的に、entityAspect.setDetachedを介してエンティティをデタッチすると、entityManager キャッシュからエンティティが完全に削除されます。これにより、クライアントのナビゲーション コレクションからもエンティティが削除されますが、EntityManager.saveChanges の呼び出し中にサーバーに影響を与えることはありません。これは、EntityManager がエンティティについて「認識」していないためです。「デタッチ」とは、エンティティが最初からクエリされていないかのように、エンティティを完全に忘れるように EntityManager に指示することだと考えてください。

エンティティを「削除」した後に同じエンティティを「再追加」すると、EntityManager が同じエンティティの 2 つの化身を持つことになるため、問題があります。削除されたバージョンと追加されたバージョン。したがって、EntityManager は、表示されている例外をスローします。

あなたがしたいことは、別のIDを持つ「新しい」クローンエンティティを削除して追加することだと思います。

これが理にかなっていることを願っています!

于 2013-10-15T17:21:39.967 に答える
2

これが発生する理由は、Breeze がそのエンティティをサーバーから完全に削除するまでそのエンティティを追跡し、同じ ID を持つ新しいエンティティを作成しないようにするためです。もちろん、同じ ID を持つ新しいエンティティを作成することはできないため、サーバー例外がスローされます。 .

再作成を試みる前に entityManager で saveChanges() を呼び出した場合、Breeze はサーバーにアクセスし、DB からエンティティを削除し、Promise を返し、ローカル キャッシュからエンティティを完全に切り離します。サーバー上。

entityState を手動で detached に設定することもできますが、saveChanges を実行しようとしてその ID がサーバーに既に存在すると、エラーがスローされます。

最良の選択肢

エンティティを配列で saveChanges メソッドに渡します -

results[0].entityAspect.setDeleted();
manager.saveChanges([results[0]]).then(saveSucceeded);

function saveSucceeded() {
    console.log('Entity removed from server');
}

saveSucceeded が完了したら、その ID で新しいエンティティを作成できます

于 2013-10-15T16:39:58.080 に答える