从breeze.js缓存中无效或清除某些实体类型

时间:2013-09-15 22:27:55

标签: breeze

在应用程序中给出一个相当标准的场景,有一个可以添加/编辑/删除的实体列表等。当我第一次加载页面时,我会轻松查询entites。都好。如果我编辑实体,breeze会看到这个并且实体在缓存中保存并更新,因此当我返回带有列表的页面时,该项目会显示任何相关的更改。如果我删除一个实体,breeze将再次保存该更改并更新它的缓存,这样当我返回列表页面并重新查询数据时,实体就不再出现了(我应该指出缓存本地)。

但是,如果我添加一个新实体,它不会出现在列表页面上(假设它满足查询的要求)。我猜breeze正在缓存特定于该查询的查询结果,而不是实际查询缓存(这是否有意义)?

假设是这种情况,是否有办法告诉breeze删除或使与特定实体类型相关的缓存项无效,而不是完全清除缓存?我总是可以避免查询缓存并直接进入服务器,但是当我知道breeze在缓存中有新创建的实体时,这似乎是浪费,它只是没有显示给我。

我对我的很多查询使用单一方法,所以它可能就是我在该方法中处理本地查询的方式,因此我将其包含在下面,以防万一。

var defaultQuery = function (observable, resourceName, orderby, where, expand, forceRemote, localEntityName, localCountThreshold, page, count) {
            var query = EntityQuery.from(resourceName);
            if (orderby) {
                query = query.orderBy(orderby);

                if (page) {
                    query = query.skip(pageSize * (page()));
                    query = query.take(pageSize);
                    query = query.inlineCount();
                }
            }
            if (where)
                query = query.where(where);
            if (expand)
                query = query.expand(expand);

            if (!forceRemote) {
                if (localEntityName) {
                    query = query.toType(localEntityName);
                }
                var localResult = manager.executeQueryLocally(query);
                if (localCountThreshold) {
                    if (localResult.length > localCountThreshold) {
                        observable(localResult);
                        return Q.resolve();
                    }
                } else {
                    if (localResult.length > 0) {
                        observable(localResult);
                        return Q.resolve();
                    }
                }
            }

            return query.using(manager)
                .execute()
                .then(function (data) {
                    if (observable) {
                        observable(data.results);
                    }
                    if (count) {
                        count(data.inlineCount);
                    }
                    var logMsg = 'Retrieved ' + resourceName + ' from remote data source with order by {' + orderby + '}, where clause {' + where + '} and expand properties {' + expand + '}';
                    if (page)
                        logMsg += ' for page {' + page() + '} with total record count {' + count() + '}';
                    log(logMsg, data, true);
                })
                .fail(queryFailed);
        };

通常在这样的问题中,我只是误解了微风如何运作的某些方面,所以如果有人能够纠正我,我会非常感激。

谢谢!


更新

我已逐步包含了行动流程,以更详细地显示我的意思。

  1. 对所有对象执行查询
  2. 首先在本地执行查询,不返回任何内容,因为不存在缓存数据。
  3. 然后对数据库执行查询 - 返回[A,B,C]
  4. 编辑A - 重命名为AA - 调用saveChanges()
  5. 对所有对象执行相同的查询
  6. 首先在本地执行查询,返回[AA,B,C]
  7. 查询跳过对数据库执行,因为已从缓存中找到结果。
  8. 删除B(setDeleted()) - 调用saveChanges()
  9. 对所有对象执行相同的查询
  10. 首先在本地执行查询,返回[AA,C]
  11. 查询跳过对数据库执行,因为已从缓存中找到结果。
  12. 创建新实体 - 将名称设置为D - 调用saveChanges()
  13. 对所有对象执行相同的查询
  14. 首先在本地执行查询,返回[AA,C](不包括新的D对象!)
  15. 我想要发现的一点是,本地查询会返回为编辑和删除而保存的更改,但不会返回添加操作。我可以使用Jay建议的setDetached从缓存中删除实体,但我需要逐个为特定类型的所有实体执行此操作。这可能是一个很大的过程。


    再次更新

    我看到的行为似乎是我自己犯了一些错误的结果。由于杰伊声称结果应该在那里(见下文),所以对所有内容进行了双重和三重检查,现在出现了“添加”对象,但老实说,我无法解释我为防止它们做了什么。

1 个答案:

答案 0 :(得分:3)

为了清楚起见,Breeze在您编辑实体时更新缓存,在您调用 EntityManager.saveChanges()之前,它不会保存该实体。因此,在调用“ saveChanges ”缓存之前,您的数据库将处于不同的状态。

您可能会看到的结果是,当您重新查询已在EntityManager中更改过的实体时,将服务器端数据与客户端缓存合并的操作由 EntityQuery控制.queryOptions.mergeStrategy 。默认情况下,EntityQuery具有 PreserveChanges 的MergeStrategy,这意味着服务器端结果不会覆盖缓存中的任何“已修改”记录。

根据帖子的后半部分,您只需调用实体的“entityAspect.setDetached”方法即可从本地缓存中删除任何实体。