3

このエラーは常に報告されていますが、アプリの動作は意図したとおりであるため、デバッグに苦労しています。それが何を意味し、どのようにそのソースをデバッグすることができるかについてのポインタをいただければ幸いです。

あいまいで申し訳ありませんが、望ましい結果が得られているため、他にどのような情報を提供すればよいかわかりません。

アップデート

この問題の再現を作成し、コードを問題に集中させようとしました。データベースが正しく更新されていても、エラーは一貫してスローされます。コードには 1 つの saveChanges があり、Breeze Todo サンプルの dataservice.js の保存機能を使用します。SaveOptions.allowConcurrentSaves は false です。

それを説明するのに完全に途方に暮れ、EFコードを調べて、明らかな間違いを犯しているかどうかを確認しましたが、それを見ることができません。WebAPI の SaveChanges メソッドに送信されたバンドルも正しいように見えます (ID などが正しく取り込まれています)。

https://github.com/DazWilkin/BreezeJS.ScoreIssue

2月6日更新

この問題は、ウェイドの役立つ回答によって未解決のままです。残念ながら、何が間違っているのか、またはこれがバグであることを理解できない限り、このプロジェクトでの Breeze の使用を放棄し、くだらない単純な古い AJAX 呼び出しに戻る必要があります。

この問題は、変更を保存するときにゼロの GUID を返すサーバーを中心に展開しているようです。メソッドはエラーを返しません。これが私のエンティティ モデルのバグであることを知ってわくわくしますが、疑わしいと思います。

失敗は次のとおりです。

微風.debug.js: 11954

var ix = this._indexMap[tempValue];
if (ix === undefined) {
   throw new Error("Internal Error in key fixup - unable to locate entity");
}

コードがこの時点に到達すると、this._indexMap の値は正しく、次のようになります。

{"bcb6e670-00fc-469d-8531-5767f40bf3c1":0}

しかし、(サーバーによる Web API 呼び出しから返される) tempValue の値は間違っています:

00000000-0000-0000-0000-000000000000

realValue は正しく、次のとおりです。

1093b975-7686-4621-8336-77c38ed36de0

スタックのバックアップ。AJAX 呼び出しの結果は、breeze.debug.js: 12574 です。サーバー/WebAPI 呼び出しからの戻り時に、tempValue がゼロになっていることを確認してください。realValue は正しいです。これがデータベースの内容です。行は問題なくテーブルに追加されます。

"KeyMappings": [
    {
        "$id": "4",
        "$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
        "EntityTypeName": "...Score",
        "TempValue": "51877f5b-811f-4260-bd5b-cf9965159597",
        "RealValue": "92b73b8a-8b33-45cd-9822-ca7c0c5d5d9a"
    },
    {
        "$id": "5",
        "$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
        "EntityTypeName": "...PropertyValue",
        "TempValue": "00000000-0000-0000-0000-000000000000",
        "RealValue": "1093b975-7686-4621-8336-77c38ed36de0"
    }

],

saveBundle でサーバー側で受信したものに対して検証されました。注意: サーバーで受信した両方のエンティティの ID には、有効な GUID ID があります。

"entities": [
    {
        "ID": "51877f5b-811f-4260-bd5b-cf9965159597",
        ...
        "entityAspect": {
            "entityTypeName": "Score:...",
            "entityState": "Added",
            "originalValuesMap": {},
            "autoGeneratedKey": {
                "propertyName": "ID",
                "autoGeneratedKeyType": "Identity"
            }
        }
    },
    {
        "ID": "bcb6e670-00fc-469d-8531-5767f40bf3c1",
        ...
        "entityAspect": {
            "entityTypeName": "PropertyValue:...",
            "entityState": "Added",
            "originalValuesMap": {},
            "autoGeneratedKey": {
                "propertyName": "ID",
                "autoGeneratedKeyType": "Identity"
            }
        }
    }
],

当然のことながら、breeze.debug.js: 10494 saveBundleStringified で作成された AJAX 呼び出しによってサーバーに送信された値は正しく、サーバーによって受信された値と同じです (再現しませんが、再現することを保証します)。

そして、私のコードから、saveChanges が呼び出されると、

manager.getChanges().length == 2
manager.getChanges()[0].ID() == "51877f5b-811f-4260-bd5b-cf9965159597" (Score)
manager.getChanges()[1].ID() == "bcb6e670-00fc-469d-8531-5767f40bf3c1" (PropertyValue)

そして、予想通り、これらはサーバーによって受信されたsaveChanges中にエンティティのIDの(一時)値と一致します...

私は何を間違っていますか?? 髪の毛があったら、引きちぎるよ!

4

4 に答える 4

5

私はそれを解決しました。

私の一貫性のない適用 (!) 規則は、セッターをコードの最初の型で内部/プライベートにすることです。すべての可能性を使い果たしたと感じた後、PropertyValue タイプ、つまりエラーの原因となったタイプに内部セットがあることを発見したため、一貫性がありません。

これを削除してソリューションを再構築すると、問題は解決しました!

そう:

public Guid ID { get; internal set; }

次のようにする必要があります。

public Guid ID { get; set; }
于 2013-02-06T22:48:57.820 に答える
3

1月27日更新:

Sergey の回答に対するコメントに基づいて、保存操作が完了する前に、変更されたエンティティで何かをしようとしていた可能性があります。

これらのエンティティは、サーバーが保存の成功を報告するまで、変更された状態のままです...多くの場合、一時的な主キーと外部キーがあります.

保存が成功するまで、おそらくそれらに触れるべきではありません。Sergey が観察しているように、保存成功のコールバックで保存後の処理を見つける必要があります。

manager.saveChanges() を返す
              .then(saveSucceeded)
              .fail(saveFailed);

saveChanges呼び出しを jQuery でラップしないでくださいDeferred。それは時間と複雑さの無駄です。このEntityManager.saveChangesメソッドは、呼び出し元が使用できる promise を返します。ビュー モデルは、独自の成功および失敗のコールバックを追加できます

dataservice.saveChanges()
           .then(万歳)
           .fail(悲しいトロンボーン);

同時保存

あなたのコードで、 Todoサンプルで見つけた時間遅延アプローチを使用して、違法な同時保存を防止していることに気付きました。

そのアプローチは、実際にはデモにのみ適しています。保存が成功したときにビューモデルがいくつかのタスクを実行する必要がある場合、それはまったく機能しません。時間遅延アプローチでは、データサービスがビュー モデルに約束を返すことができないため、機能しません。

ノンブロッキング セーブが必要な場合は、「Cool Breezes」セクションの「 Concurrent Saves 」トピックで説明されている「 Save Queuing」プラグインをチェックしてください。

エンティティを簡潔に作成する

あなたのコードを見ていると、scoreissue.1.0.tsのエンティティ ファクトリ メソッドが少し冗長であることに気付きました。あなたが書いたもの:

export function Business(manager, o: IBusiness) {
  var ビジネス = manager.metadataStore.getEntityType("ビジネス").createEntity();
  business.ID(breeze.core.getUuid());
  business.Name(o.name);
  manager.addEntity(ビジネス);
  返品事業;
}

次のように簡単です。

export function Business(manager, o: IBusiness) {
  return manager.createEntity("ビジネス", {
    ID:そよ風.core.getUuid()、
    名前: o.name,
  });
}

あなたがこのEntityManager.createEntityコードを書いて以来、ショートカットは新しいものなので、見落としても気にしないでください。

元の答え:

【方向を間違えた。問題はクライアントにあるという DazWilkin のコメントを理解するために保存されています。]

これはどこで生成されていますか?サーバー上?その場合は、EFContextProvider をサブクラス化し、オーバーライドすることができますSaveChangesCore。を呼び出してbase.SaveChangesCore、try/catch で囲みます。saveMap引数を調べます。EFContextProvider はオープン ソースです。ここから掘り始めます。

于 2013-01-04T22:20:34.480 に答える
1

私は同じ問題を抱えており、jQuery deferred オブジェクトの助けを借りて解決しました。私のデータサービス保存方法は次のようになりました:

saveChanges = function () {
    var def = $.Deferred();

    if (manager.hasChanges()) {
        manager.saveChanges()
            .then(function () { def.resolve() })
            .fail(function (error) {
                handleSaveError(error);
                def.reject();
            });
    } else {
        logger.info("Nothing to save");
        def.resolve();
    };

    return def.promise();
};

そして、jQuery 遅延オブジェクトも使用して、ビュー モデルから呼び出します。

$.when(dataservice.saveChanges())
 .done(function () {
      ...some actions
 })
于 2013-01-21T21:19:23.833 に答える
1

このエラーは、複数の同時保存要求が同時に保留されている場合に発生する可能性があり、両方ともキー生成が関係しています。このエラーは保存中にのみ発生しますか? その場合は、SaveOptions.allowConcurrentSaves を false に設定してみてください。これにより別のエラー (同時保存エラー) が発生する場合、問題は間違いなく同時保存に関係しています。

お役に立てれば。

于 2013-01-04T22:15:01.203 に答える