Breeze JS:有没有办法从data.results查询实体?

时间:2013-10-01 18:56:33

标签: javascript breeze single-page-application hottowel

我有一个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);

        }

2 个答案:

答案 0 :(得分:4)

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

我必须希望您知道自己在做什么,并且无意保留对这些客户实体的更改,而这些客户实体仍然可能会造成其他灾难。

请注意,当您将所选客户导入“localManager”时,您未携带相关的Organization实体。这意味着诸如resultProjection[0].organization之类的表达式将返回null。这似乎不正确。

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

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

首先,我会将所有这些逻辑埋没在DataContext本身内; DataContext的目的是封装数据访问的细节,以便调用者(例如ViewModels)不必知道内部。 DataContext是UnitOfWork(UoW)模式的一个示例,它是一种抽象,有助于隔离ViewModel关注的数据访问/操作问题。

然后我将它存储在DataContext(DC)或ViewModel(VM)的命名数组中,具体取决于该子集是否对应用程序有狭隘或广泛的兴趣。

如果只有VM实例关心此子集,则DC应返回data.results并让VM保留它们。

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

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

当然这不会给你类似Breeze LINQ的查询语法......但你真的需要吗?你为什么需要“。选择”那套?

如果真的需要,那么我想我明白为什么你要将结果转储到一个单独的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();

我相信您会知道如何在回调我们的“GetActiveCustomers”查询时正确设置subset属性。

HTH

答案 1 :(得分:0)

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

您需要做的就是在需要过滤数据时在本地查询。 您可以通过指定管理器在本地查询来执行此操作:

manager.executeQueryLocally(query);

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