3

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

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

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

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

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对象!)

我试图发现的一点是本地查询返回为编辑和删除而保存的更改,但不是为添加操作。我可以按照 Jay 的建议使用 setDetached 从缓存中删除实体,但我需要为特定类型的所有实体一个接一个地执行此操作。这可能是一个很大的过程。


再次更新

看来我看到的行为是我自己的一些错误的结果。由于 Jay 断言结果应该在那里(见下文),对所有内容进行了双重和三重检查,“添加”的对象现在出现了,但老实说,我无法解释我首先做了什么来阻止它们。

4

1 回答 1

3

需要明确的是,Breeze 在您编辑实体时会更新缓存,在您调用EntityManager.saveChanges()之前它不会保存该实体。因此,在您调用“ saveChanges ”之前,缓存和您的数据库将处于不同的状态。

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

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

于 2013-09-16T16:50:14.283 回答