我有一个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);
}
答案 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或某种服务类中。我不希望我的虚拟机知道任何这些恶作剧。
祝你好运。
在睡觉之后,我有另一个想法,在这个用例中消除了对第二个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);
因为从数据库中查询是异步完成的,所以必须确保仅在存在某些内容时才从本地内存中检索。遵守承诺。