1

我有一个 Breeze web api 控制器,其方法在服务器上接受参数并执行一些工作、过滤、排序等。在 querySucceeded 上,我想进一步查询 data.results。有没有办法做到这一点?我通过将 data.results 导出/导入到本地经理来完成这项工作,并从那里进行投影。为了在供应商网格控件中使用可观察集合,需要进行投影。

        var query = datacontext.EntityQuery.from("GetActiveCustomers")
            .withParameters({ organizationID: "1" })
            .toType("Customer")
            .expand("Organization")
            .orderBy('name');

        var queryProjection = query
                .select("customerID, organizationID, name, isActive, organization.name");

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

        function querySucceeded(data) {
            var exportData = manager.exportEntities(data.results);
            var localManager = breeze.EntityManager.importEntities(exportData);
            var resultProjection = localManager.executeQueryLocally(queryProjection); 
    //This is the way I came up with to query data.results (exporting/importing the result entities to a local manager)
    //Is there a better way to do this? Querying directly data.results. Example: data.results.where(...).select("customerID, organizationID...)

            if (collectionObservable) {
                collectionObservable(resultProjection);
            }
            log('Retrieved Data from remote data source',
                data, true);

        }
4

2 回答 2

4

你采取了一种有趣的方法。通常,投影返回不可缓存的对象,而不是实体。但是您将其转换为Customer(使用该toType子句),这意味着您已经创建Customer了缺少数据的 PARTIAL 实体。

我必须希望您知道自己在做什么,并且无意将更改保存到这些客户实体,而它们仍然是局部的,否则可能会发生灾难。

请注意,当您将选定的客户导入“localManager”时,您并没有带上他们的相关Organization实体。这意味着诸如resultProjection[0].organization将返回 null 的表达式。这似乎不正确。

我了解您希望保留Customer部分实体的子集,并且没有本地查询可以从缓存中选择该子集,因为选择标准仅在服务器上完全知道。

我想我会以不同的方式处理这种需求。

首先,我会将所有这些逻辑隐藏在DataContext它自身中;a 的目的DataContext是封装数据访问的细节,以便调用者(例如 ViewModels)不必了解内部情况。这DataContext是 UnitOfWork (UoW) 模式的一个示例,该模式有助于将数据访问/操作问题与 ViewModel 问题隔离开来。

然后,我会将其存储在DataContext(DC) 或 ViewModel (VM) 的命名数组中,具体取决于该子集在应用程序中是狭义的还是广义的。

如果只有 VM 实例关心这个子集,那么 DC 应该返回data.results并让 VM 持有它们。

我不明白您为什么要为此集合重新查询本地 EntityManager,也不明白为什么您的本地查询还应用投影......这会将非实体数据对象返回给调用者。返回(部分)客户实体有什么问题。

您似乎打算进一步过滤客户端上的子集。嘿……这是一个 JavaScript 数组。你可以打电话stuffArray.filter(filterFunction)

当然,这不会为您提供类似 Breeze LINQ 的查询语法……但您真的需要吗?为什么你需要在那个集合上使用“.select”?

如果这真的是您的需要,那么我想我理解您为什么将结果转储到单独的 EntityManager 以供本地使用。在这种情况下,我相信您的查询回调方法中需要更多代码来将相关Organization实体导入到本地 EM 中,以便someCustomer.organization返回一个值。这种方法不断增加的技巧让我感到不舒服,但这是你的应用程序。

如果您继续沿着这条路走下去,我强烈建议您将其封装在 DC 中或某种服务类中。我不希望我的虚拟机知道这些恶作剧。

祝你好运。

2013 年 10 月 3 日更新:未映射属性上的本地缓存查询过滤

在上面睡觉之后,我有另一个想法给你,在这个用例中消除你对第二个 EM 的需要。

您可以向客户端Customer实体添加未映射的属性,并在查询服务器上的“GetActiveCustomers”端点后使用子集标记设置该属性;您将在查询回调中设置标记。

然后,您可以编写一个本地查询来过滤标记值,以确保您只考虑Customer该子集中的对象。

仅在本地查询中引用标记值。我不知道对标记值的远程查询过滤是否会失败或只是忽略该标准。

您不需要单独的本地 EntityManager;主管理器中的Customer实体带有服务器端过滤的证据。当然,服务器将永远不必处理您未映射的属性值。

是的,轻而易举的本地查询可以针对未映射的属性以及映射的属性。

这是一个小演示。像这样注册一个自定义构造函数:

function Customer() { /* Custom constructor ... which you register with the metadataStore*/
    // Add unmapped 'subset' property to be queried locally.
    this.subset = Math.ceil(Math.random() * 3); // simulate values {1..3}
}

稍后您在本地查询它。以下是引用和不引用该属性的查询示例:

// All customers in cache
var x = breeze.EntityQuery.from("Customers").using(manager).executeLocally();

// All customers in cache whose unmapped 'subset' property === 1.
var y = breeze.EntityQuery.from("Customers")
        .where("subset", 'eq', 1) // more criteria; knock yourself out
        .using(manager).executeLocally();

我相信您会知道如何subset在对“GetActiveCustomers”查询的回调中适当地设置属性。

高温高压

于 2013-10-03T00:02:06.447 回答
0

一旦您查询了一些数据,轻而易举地将这些实体存储在本地内存中。

当您需要进一步过滤数据时,您所要做的就是在本地查询。您可以通过指定经理在本地查询来做到这一点:

manager.executeQueryLocally(query);

因为从数据库中查询是异步完成的,所以您必须确保只有在本地内存中有内容时才从本地内存中检索。遵守承诺。

于 2013-10-02T16:33:19.310 回答