你快到了! :-) 如果您在查询中指定了目标EntityType,我认为它会起作用。
试试这个:
var query = EntityQuery.from(resource).orderBy(ordering).
toType('Esto');
toType() 方法告诉 Breeze,此查询返回的顶级对象将是 Esto 类型。
为什么?
让我们考虑一下 Breeze 如何解释查询规范。
请注意,您开始查询时,正如我们通常所做的那样,通过命名将提供数据的资源。此资源通常是到远程服务端点的路径段,可能是 Web API 控制器方法的名称……一个名为“Foos”的方法。
了解查询资源名称很少与EntityType 名称相同!它们可能相似 - “Foos”(复数)类似于类型名称“Foo” (单数)。但资源名称可能是别的东西。它可能是“GetFoos”或“GreatFoos”或任何东西。重要的是服务方法返回“Foo”实体。
Breeze 需要一种将 resource 名称与 EntityType 名称相关联的方法。 Breeze 本身并不知道相关性。 toType() 方法是告诉 Breeze 的一种方式。
为什么没有toType() 远程查询可以工作?
您通常不会在查询中添加toType()。为什么是现在?
大多数时候 [1],Breeze 不需要知道EntityType 直到数据从服务器到达。当 JSON 查询结果包含类型名称时(例如,当它们来自 Breeze Web API 控制器时),Breeze 可以在没有我们帮助的情况下将到达的 JSON 数据映射到实体中……假设这些类型名称在元数据中。
本地缓存查询不同
当您查询缓存时...比如说executeQueryLocally...Breeze 必须知道要搜索哪个缓存的实体集才能在本地查询。
它“知道”你是否用toType() 指定类型。但是,如果您省略 toType(),Breeze 将不得不使用查询的资源名称。
Breeze 不会猜。相反,它会在 EntityType/ResourceName 映射中查找与查询资源名称匹配的实体集。
资源名称指的是服务端点,而不是缓存的实体集。例如,没有名为“Informacion”的实体集。因此 Breeze 使用 EntityType/ResourceName 映射来查找与查询资源名称关联的实体类型。
实体类型/资源名称
EntityType/ResourceName 映射是 Breeze MetadataStore 中的项目之一。你可能从未听说过它。那挺好的;你不应该考虑它......除非你做一些不寻常的事情,比如定义你自己的类型。
新MetadataStore 的地图一开始是空的。如果这些元数据包含 EntityType/Resource 映射,Breeze 会从服务器元数据中填充它。
例如,Breeze EFContextProvider 使用从 DbSet 名称派生的映射生成元数据。当您定义Foo 类并将其从DbContext 公开为名为“Foos”的DbSet 时,EFContextProvider 元数据生成器添加从“Foos”资源名称到Foo 实体类型的映射。
控制器开发人员倾向于使用DbSet 名称作为方法名称。传统的 Breeze Web API 控制器“Foo”查询方法如下所示:
[得到]
公共 IQueryable
Foos() {...}
现在,如果您进行这样的查询:
var query = EntityQuery.from('Foos').where(...);
并将其应用于缓存
manager.query.executeLocally(query).then(...);
它只是工作。
为什么?因为
- “Foos”是服务器上
DbSet 的名称
-
EFContextProvider 生成的元数据映射 ["Foos" 到 Model.Foo]
- Web API 控制器提供
Foos 操作方法。
- BreezeJS
query 指定“Foos”
-
executeLocally 方法在元数据中查找 ["Foos"-to-Model.Foo] 映射,并将查询应用于Foo 的实体集。
端到端约定对您有利。
...直到您提到不在 EntityType/ResourceName 映射中的资源名称!
注册资源名称
没问题!
您可以添加自己的资源到实体类型的映射,如下所示:
var metadataStore = manager.metadataStore;
var typeName = '一些类型名称';
var entityType = metadataStore.getEntityType(typeName);
metadataStore.setEntityTypeForResourceName(resource, entityType);
Breeze 也对类型的名称感到满意:
metadataStore.setEntityTypeForResourceName(resource, typeName);
在您的情况下,在您的 DataContext 顶部附近的某处,您可以写:
var metadataStore = manager.metadataStore;
// 将两个资源名称映射到 Esto
metadataStore.setEntityTypeForResourceName('Esto', 'Esto');
metadataStore.setEntityTypeForResourceName('Informacion', 'Esto');
不要过度使用toType()
当您需要将查询结果中的顶级对象映射到EntityType 时,toType() 方法是一个很好的捷径解决方案。您不必为注册资源名称而烦恼。
但是,您必须记住将toType() 添加到每个需要它的查询中。使用资源到实体类型的映射配置 Breeze 元数据,您每次都会获得所需的行为。
注意事项
[1]“大多数情况下,Breeze 在数据从服务器到达之前不需要知道EntityType。”一个重要的例外 - 超出了本次讨论的范围- 当查询过滤器涉及日期/时间时。