我正在使用Papa的CCJS代码来调查Breeze.js和SPA。使用此代码我试图管理来自服务器但不是来自EntityFramework的元数据中包含的实体的附加信息。
所以我创建了一个名为Esto的NO-DB类和一个像Lookups这样的服务器方法:
[HttpGet]
public object Informacion()
{
var a = new Esto(....);
var b = new Esto(.....);
var c = new Esto(......);
return new {a,b,c};
}
然后在configureMetadataStore里面的model.js中调用:
metadataStore.addEntityType({
shortName: "Esto",
namespace:"CodeCamper",
dataProperties:{
id: {dataType: breeze.DataType.Int32,isPartOfKey: true},
name: {dataType: breeze.DataType.String}
}
};
并在模型entityNames数组中定义:esto:'Esto'作为实体
现在在context.js中我加载这个创建服务器端方法,如getLookups,但称为getInformacion:
function getInformacion(){
return EntityQuery.from('Informacion')
.using(manager).execute()
}
然后在success方法中的primeData中调用this:
datacontext.informacion = {
esto: getLocal('Esto',nombre)};
其中getLocal是:
function getLocal(resource, ordering)
{
var query = EntityQuery.from(resource).orderBy(ordering);
return manager.executeQueryLocally(query);
}
我在getLocal中包含的查询中收到一条错误,指出无法找到entityTypeName的EntityType:'undefined'或resourceName:'Esto'。
我做错了什么?
由于
答案 0 :(得分:10)
你快到了! :-)如果你在查询中指定了目标EntityType
,我认为它会起作用。
试试这个:
var query = EntityQuery.from(resource).orderBy(ordering).toType('Esto');
toType()
方法告诉Breeze,此查询返回的顶级对象的类型为Esto
。
让我们考虑Breeze如何解释查询规范。
请注意,您通常会通过命名将提供数据的资源来开始查询。此资源通常是远程服务端点的路径段,可能是Web API控制器方法的名称......名为“Foos”的方法。
了解查询资源名称与EntityType
名称很少相同至关重要!它们可能类似 - “Foos”(复数)类似于类型名称“ Foo“(单数)。但资源名称可能是其他东西。它可能是“GetFoos”或“GreatFoos”或任何东西。重要的是服务方法返回“Foo”实体。
Breeze需要一种方法将资源名称与 EntityType
名称相关联。 Breeze不知道自己的相关性。 toType()
方法是告诉Breeze的一种方法。
toType()
的情况下工作?您通常不会在查询中添加toType()
。为什么现在?
大部分时间[1],Breeze不需要知道EntityType
,直到数据从服务器到达 。当JSON查询结果包含类型名称时(例如,当它们来自Breeze Web API控制器时),Breeze可以在没有我们帮助的情况下将到达的JSON数据映射到实体中...假设这些类型名称在元数据中。
当您查询缓存时......请说出executeQueryLocally
... Breeze必须知道哪个缓存的实体集在本地查询之前搜索
如果您使用toType()
指定类型,则“知道”。但如果省略toType()
,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”查询方法如下所示:
[Get] public IQueryable<Foo> Foos() {...}
现在,如果您进行如下查询:
var query = EntityQuery.from('Foos').where(...);
并将其应用于缓存
manager.query.executeLocally(query).then(...);
它只是有效。
为什么呢?因为
DbSet
的名称EFContextProvider
生成的元数据映射[“Foos”到Model.Foo
] Foos
操作方法。query
指定“Foos”executeLocally
方法在元数据中找到[“Foos” - 到 - Model.Foo
]映射,并将查询应用于Foo
的实体集。端到端的约定默默地对你有利。
...直到您提到不在EntityType / ResourceName映射中的资源名称!
没问题!
您可以按如下方式添加自己的资源到实体类型的映射:
var metadataStore = manager.metadataStore; var typeName = 'some-type-name'; var entityType = metadataStore.getEntityType(typeName); metadataStore.setEntityTypeForResourceName(resource, entityType);
Breeze也很满意这个类型的名称:
metadataStore.setEntityTypeForResourceName(resource, typeName);
在你的情况下,在DataContext
顶部附近,你可以写:
var metadataStore = manager.metadataStore; // map two resource names to Esto metadataStore.setEntityTypeForResourceName('Esto', 'Esto'); metadataStore.setEntityTypeForResourceName('Informacion', 'Esto');
toType()
当您需要将查询结果中的顶级对象映射到toType()
时,EntityType
方法是一个很好的快捷方法。您不必乱用注册资源名称。
但是,您必须记住将toType()
添加到需要它的每个查询中。使用资源到实体类型映射配置Breeze元数据,每次都会获得所需的行为。
[1]“大部分时间,在数据从服务器到达之前,Breeze不需要知道EntityType
。”一个重要的例外 - 超出范围此讨论 - 是查询过滤器涉及日期/时间的时间。
答案 1 :(得分:1)
我认为这里的问题是你假设实体类型名称和资源名称是相同的。资源名称是用于执行查询的名称
var q = EntityQuery.from(resourceName);
在您的情况下,“resourceName”是“Informacion”,entityType实际上是“Esto”。 Breeze能够在远程查询上建立此连接,因为它可以检查从服务器返回的结果,因为查询“Informacion”并看到它们实际上是“Esto”实例。这对于本地查询是不可能的,因为Breeze不知道从哪个本地集合开始。
在这种情况下,您需要通过 MetadataStore.setEntityTypeForResourceName 方法为Breeze提供更多信息。像这样:
var estoType = manager.metadataStore.getEntityType("Esto");
manager.metadataStore.setEntityTypeForResourceName("Informacion", estoType);
请注意,如果资源是通过Entity Framework元数据定义的,则实际上不需要这样做,因为Breeze会自动将所有EF EntitySet名称与资源名称相关联,但此信息不适用于DTO。
另请注意,单个实体类型可以包含任意数量的resourceNames。只需确保在尝试本地查询之前注册resourceNames。