4

Breeze を使用してデータをクエリするアプリがあります。最初にローカル キャッシュをチェックし、結果が返されない場合はサーバー キャッシュをチェックします (John Papa の SPA ジャンプスタート コースに従いました)。ただし、ロジックに欠陥があり、修正方法がわかりません。クエリに一致するアイテムが 10 個あるとします。

状況 1 (動作): 10 個すべてを表示するリスト ページ (ページ A) に移動します。キャッシュが空であるためサーバーにヒットし、10 個すべてをキャッシュに追加します。次に、キャッシュにある 1 つの結果を表示しているページ (ページ B) に移動します。だからすべて良い。

状況 2 (問題): 最初に 1 件のレコードが表示されているページ (ページ B) に移動します。次に、キャッシュをチェックして 1 つのレコードを見つけるリスト ページ (ページ A) に移動します。この行 ( if (recordsInCache.length > 0)) のために終了し、その 1 つのレコードのみが表示されます。

私はどういうわけか、キャッシュにないサーバー (9) にもっと多くのレコードがあることを知る必要があります。このクエリの合計レコードは実際には 10 です。1 つあるため、残りの 9 についてはサーバーにアクセスする必要があります。

ページ A に対するクエリは次のとおりです。

function getDaresToUser(daresObservable, criteria, forceServerCall)
{
    var query = EntityQuery.from('Dares')
        .where('statusId', '!=', enums.dareStatus.Deleted)
        .where('toUserId', '==', criteria.userId)
        .expand("fromUser, toUser")
        .orderBy('deadlineDate, changedDate');

    return dataServiceHelper.executeQuery(query, daresObservable, false, forceServerCall);
}

そして、これがページB(単一アイテム)に対する私のクエリです

function getDare(dareObservable, criteria, forceServerCall)
{
    var query = EntityQuery.from('Dares')
        .expand("fromUser, toUser")
        .where('dareId', '==', criteria.dareId);

    return dataServiceHelper.executeQuery(query, dareObservable, true, forceServerCall);
}



function executeQuery(query, itemsObservable, singleEntity, forceServerCall)
{
    //check local cache first
    if (!manager.metadataStore.isEmpty() && !forceServerCall)
    {
        var recordsInCache = executeLocalQuery(query, itemsObservable, singleEntity);
        if (recordsInCache.length > 0)
        {
            callCompleted();
            return Q.resolve();
        }
    }

return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

}

function executeLocalQuery(query, itemsObservable, singleEntity)
{
    var recordsInCache = manager.executeQueryLocally(query);
    if (recordsInCache.length > 0)
    {
        processQueryResults(recordsInCache, itemsObservable, singleEntity, true);
    }
    return recordsInCache;
}

アドバイスをいただければ幸いです...

4

2 に答える 2

1

比較目的でサーバーにアクセスしたいだけの場合は、ある時点(アプリをロードするとき、またはリストページにアクセスするとき)で inlineCount を呼び出して、サーバーの合計と、この回答に示されているように既に持っているものを比較しますstackoverflow.com /questions/16390897/counts-in-breeze-js/…

単一のレコードを照会しているときにこれを創造的に使用できる方法は、次のようになります-

ビューモデルに変数を設定するか、合計数に等しい場所に設定します

var totalCount = 0;

単一のレコードをクエリすると、インライン カウントが取得されます -

var query = EntityQuery.from('Dares')
    .expand("fromUser, toUser")
    .where('dareId', '==', criteria.dareId)
    .inlineCount(true);

合計アイテムリストを取得するときに同じことを設定totalCount = data.inlineCount;します.totalCountをinlineCountに設定するだけで、すべてのエンティティがあるかどうかを常に知ることができます.

于 2013-08-12T13:37:43.933 に答える
0

私は昨年、この問題についてもっと考えていました (そして、それ以来、Durandal + Breeze から Angular + Breeze に移行しました: Angular では、次を使用してサービス呼び出しを簡単にキャッシュできます)

return $resource(xyz + params}, {'query': { method:'GET', cache: true, isArray:true }}).query(successArrayDataLoad, errorDataLoad);

Angular はこのクエリのパラメーターをキャッシュし、いつそれが既にあるかを知っていると思います。したがって、このメソッドを Breeze を使用するように切り替えると、この機能が失われ、すべての List 呼び出しが毎回実行されます。

したがって、ここでの本当の問題はListデータです。単一エンティティは常にローカル キャッシュをチェックでき、何も返されない場合はサーバーをチェックします (正確に 1 が予想されるため)。

ただし、List データはパラメータによって異なります。たとえば、CreatedByUserId を受け取る GetGames 呼び出しがある場合、新しい CreatedByUserId を提供するたびに、サーバーに戻る必要があります。

したがって、リスト呼び出しをキャッシュするためにここで本当に必要なことは、QueryName と Params の組み合わせである各呼び出しのキーをキャッシュすることだと思います。

たとえば、UserID 1 の場合は GetGames1、UserId 2 の場合は GetGames2 です。

ロジックは次のようになります: Angular キャッシュをチェックして、この呼び出しがこのセッションで以前に行われたかどうかを確認します。存在する場合は、最初にローカル キャッシュを確認します。何も返されない場合は、サーバーを確認してください。

そうでない場合は、サーバーを確認してください。ローカル キャッシュにはこのクエリのデータが含まれている可能性がありますが、完全なセットであるとは限りません。

それを回避する唯一の方法は、最初に毎回サーバーにアクセスしてその Query + Params のカウントを取得し、次にローカル キャッシュにアクセスしてカウントを比較することですが、それはより非効率的です。

考え?

于 2014-11-15T07:03:11.340 に答える