我正在使用Papa的课程CCJS代码研究Breeze.js和SPA。我试图使用此代码来管理来自服务器的附加信息,但该信息不是来自EntityFramework的元数据中包含的实体。
因此,我创建了一个称为Esto的NO-DB类和一个类似于Lookups的Server方法:
[HttpGet]
public object Informacion()
{
var a = new Esto(....);
var b = new Esto(.....);
var c = new Esto(......);
return new {a,b,c};
}
然后在configure.etadataStore内部的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()
}
然后在成功方法中的primeData内部调用:
datacontext.informacion = {
esto: getLocal('Esto',nombre)};
getLocal在哪里:
function getLocal(resource, ordering)
{
var query = EntityQuery.from(resource).orderBy(ordering);
return manager.executeQueryLocally(query);
}
我在getLocal所包含的查询中遇到一个错误,指出找不到为EntityTypeName:'undefined'或resourceName:'Esto'的EntityType。
我做错了什么?
谢谢
最佳答案
你快到了! :-)如果您在查询中指定了目标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 /资源名称
EntityType / ResourceName映射是Breeze MetadataStore
中的一项。您可能从未听说过。非常好;除非您做了一些不寻常的事情,例如定义自己的类型,否则您不必考虑它。
新的MetadataStore
的映射开始为空。如果那些元数据包含EntityType /资源映射,则Breeze从服务器元数据填充它。
例如,Breeze EFContextProvider
生成具有从DbSet
名称派生的映射的元数据。当您定义一个Foo
类并将其从名为DbContext
暴露于DbSet
时,EFContextProvider
元数据生成器会添加从“ Foos”资源名称到Foo
实体类型的映射。
控制器开发人员倾向于使用DbSet
名称作为方法名称。常规的Breeze Web API控制器“ Foo”查询方法如下所示:
[得到]
公共IQueryable
现在,如果您进行如下查询:
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”到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;
//将两个资源名称映射到Esto
metadataStore.setEntityTypeForResourceName('Esto','Esto');
metadataStore.setEntityTypeForResourceName('Informacion','Esto');
不要过度使用toType()
当需要将查询结果中的顶级对象映射到toType()
时,EntityType
方法是一个很好的捷径解决方案。您不必弄乱注册资源名称。
但是,您必须记住将toType()
添加到需要它的每个查询中。使用资源到实体类型的映射配置Breeze元数据,您每次都会得到所需的行为。
笔记
[1]“大多数时候,Breeze直到数据从服务器到达后才需要知道EntityType
。”一个重要的例外情况(不在此讨论范围内)是查询过滤器涉及日期/时间。
关于breeze - Breeze用数据库实体类型管理NODB实体类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16392601/