在Breeze JS中查询服务器之前首先查询本地缓存

时间:2013-08-12 10:51:35

标签: breeze

我有一个使用Breeze查询数据的应用程序。我想首先检查本地缓存,然后检查服务器缓存,如果没有返回结果(我遵循John Papa的SPA快速启动课程)。但是,我发现我的逻辑存在缺陷,我不确定如何解决。假设我有10个与我的查询匹配的项目。

情况1 (有效):我转到列表页面(页面A),显示全部10.点击服务器作为缓存为空并将全部10添加到缓存。然后转到显示缓存中找到的1个结果(页面B)的页面。一切都很好。

情境2 (问题):我转到首先显示1条记录的页面(页面B)。然后我转到我的列表页面(页面A),它检查缓存并找到1条记录,因为这行(if (recordsInCache.length > 0))它退出并且只显示1条记录。

我不知何故需要知道服务器(9)上有更多不在缓存中的记录,即。这个查询的总记录实际上是10,我有1,因此我必须为其他9个命中服务器。

以下是我对Page 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);
}

这是我对Page 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;
}

任何建议表示赞赏......

2 个答案:

答案 0 :(得分: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,这样您就可以知道是否拥有所有实体。

答案 1 :(得分:0)

我在去年更多地考虑过这个问题(之后从Durandal + Breeze转移到Angular + Breeze:在Angular中你可以使用

轻松缓存服务调用
return $resource(xyz + params}, {'query': { method:'GET', cache: true, isArray:true }}).query(successArrayDataLoad, errorDataLoad);

我猜Angular会缓存此查询的 params 并知道它何时已经存在。因此,当我将此方法切换为使用Breeze时,我会丢失此功能,并且每次都会触发所有列表调用。

所以这里真正的问题是列表数据。单个实体总是可以检查本地缓存,如果没有返回任何内容,则检查服务器(因为您期望正好1)。

但是,列表数据因参数而异。例如,如果我有GetGames调用,它接受CreatedByUserId,每次我提供一个新的CreatedByUserId时,我必须返回服务器。

所以我认为我真正需要做的就是缓存我的List调用是为每个调用缓存Key,它是QueryName和Params的组合。

例如,UserID 1为GetGames1,UserId为2为GetGames2。

逻辑是:检查Angular缓存以查看此会话之前是否已进行此调用。如果有,则首先检查本地缓存。如果没有返回任何内容,请检查服务器。

如果没有,请检查服务器是否为本地缓存MIGHT中有一些数据用于此查询,但不保证是完整集。

唯一的另一种方法是每次首先点击服务器以获取Query + Params的计数,然后点击本地缓存并比较计数,但效率更低。

思想?