![](/img/trans.png)
[英]Breeze: addEntityType with complexType (entityTypes aggregation)
[英]Breeze EntityQuery missing data in EntityTypes returned
我正在使用Angular和Breeze建立SPA。 我一直在从复数网站关注John Papa的热巾教程。 我有一个奇怪的问题,我认为可能会从我的元数据产生? 但最后,我并不确定......
首先,我的API正在运行LAMP堆栈,所以我没有使用EF。 我创建了一个元数据端点,我认为它给了我正确的结构。 我正在使用breeze.angular.q.js来帮助我从Q到$ q的映射
资源:api / v1 /元数据
{
"metadataVersion": "1.0.5",
"dataServices": [
{
"serviceName": "api/v1/",
"hasServerMetadata": true,
"jsonResultsAdapter": "webApi_default",
"useJsonp": false
}
],
"structuralTypes": [
{
"shortName": "tracks",
"namespace": "MyNamespace",
"dataProperties": [
{
"name": "id",
"nameOnServer": "id",
"maxLength": 36,
"validators": [],
"dataType": "Guid",
"isPartOfKey": true
},
{
"name": "title",
"nameOnServer": "title",
"maxLength": 255,
"validators": [],
"dataType": "String"
},
{
"name": "description",
"nameOnServer": "description",
"maxLength": 0,
"validators": [],
"dataType": "String"
}
]
}
]
}
示例API返回数据如下所示:
资源:api / v1 / tracks
{
"data": [
{
"id": "495f21d6-adfc-40b6-a41c-fc93d9275e24",
"title": "harum",
"description": "Error doloribus ipsam et sunt fugiat."
},
{
"id": "d7b141d2-6523-4777-8b5a-3d47cc23a0fe",
"title": "necessitatibus",
"description": "Voluptatem odit nulla maiores minima eius et."
}
],
"embeds": [
"courses"
]
}
现在w /我的所有代码,我实际上是从我的api返回正确的数据。 我已经把微风网站上的例子作为我在SO上找到的一些好花絮( 这个问题和来自病房的好答案 )。 唉,没有运气。 基本上发生的事情是当我尝试在我的视图模型中循环我的结果时,从我的微风查询返回,我得到一个角度错误Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: t in vm.tracks, Duplicate key: object:00I
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: t in vm.tracks, Duplicate key: object:00I
调用发生在我的datacontext中的一个函数中。 我的querySucceeded promise回调中返回的数据似乎没有被正确绑定。
datacontext.js
...
function getTrackPartials() {
...
return EntityQuery.from(entityNames.track)
.toType(entityNames.track)
.using(manager).execute()
.then(querySucceeded, _queryFailed);
function querySucceeded(data) {
console.log(data); // <-- Log out to see what is returned
tracks = data.results;
_areTracksLoaded(true)
log('Retrieved [Track Partials] from remote data source', tracks.length, true);
return tracks;
}
}
如果我将这些数据记录到控制台,我得到这个(所有的$$ hashKey是相同的,id,title,description都是NULL。但是我得到了正确的结果数,这不是'巧合 - 如果我调整我应该接收的结果数量,它每次都正确匹配)。
现在,由于我的数据有点不同 - 我使用了Edmonds示例并创建了一个自定义的JsonResultsAdapter
因此我可以“按摩”数据。 目前它非常简陋,因为我只是想让它起作用。 什么真的让我失望,如果我从visitNode
中的JsonResultsAdapter
函数注销node
参数,它有正确的数据.... ???
entityManagerFactory.js
(function () {
'use strict';
var serviceId = 'entityManagerFactory';
angular.module('app').factory(serviceId, ['config', emFactory]);
function emFactory(config) {
breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
breeze.NamingConvention.camelCase.setAsDefault();
var serviceName = config.remoteServiceName;
var metadataStore = new breeze.MetadataStore();
var provider = {
metadataStore: metadataStore,
newManager: newManager
};
var jsonResultsAdapter = new breeze.JsonResultsAdapter({
name: "Tracks",
extractResults: function(json) {
console.log(json.results.data); // <-- Log out to see what is returned
return json.results.data;
},
visitNode: function(node, mappingContext, nodeContext) {
console.log(node); // <-- Log out to see what is returned
return {
entityType: 'tracks',
nodeId: node.id
};
}
});
var dataService = new breeze.DataService({
serviceName: serviceName,
jsonResultsAdapter: jsonResultsAdapter
});
return provider;
function newManager() {
var mgr = new breeze.EntityManager({
dataService: dataService,
metadataStore: metadataStore
});
return mgr
}
}
})();
这是我的JsonResultsAdapter :: extractResults函数的返回值
这是我的JsonResultsAdapter :: visitNode函数中的一个节点
任何帮助,将不胜感激。 就像我说的,我不确定错误发生在哪里? 但是,如果我不得不猜测,我会说我的EntityQuery使用我的经理和JsonResultsAdapter之间存在一些脱节,这可能是由我生成的错误元数据引起的。
** 更新 **
所以我浏览了微风代码,找出了我丢失数据的地方,并且能够弄清楚最新情况和解决方法。 但是,我不确定这是否是实际处理此问题的最佳方法。
我应该提一下,我用凉亭来安装微风 - 通过这样做我去了bower-breeze-angular git://github.com/eggers/bower-breeze-angular.git
包而不是默认的微风breeze git://github.com/IdeaBlade/Breeze.git
随着示例和其他数据而膨胀,我并不热衷于打包到我的回购中。
在微风中,在我的JsonResultsAdapter::visitnode
回调返回之后,它需要“ 合并 ”我的数据,我遇到的问题是从我的节点返回的entityKey不匹配。 这是因为rawValueFn从我mappingContext
正在寻找nameOnServer
,我认为我在从我的服务器我的元数据集-但不知何故,当我登录了我的dataproperty它已经从我的设置改变。
这是一个dp注销,如果你回顾我的元数据资源调用中的顶部,我特意将其设置为“id”。 这是如何改变为Id的? 那是什么导致我的头痛!
我可以通过在我的JsonResultsAdapter中的mappingContext上更新我的rawValueFn函数来解决这个JsonResultsAdapter
,一切都会起作用 - 但这感觉就像是“黑客”。 我也试过玩“NamingConvention”,但这似乎也不起作用。
这是我更新的JsonFactory,它使它工作
var jsonResultsAdapter = new breeze.JsonResultsAdapter({
name: "Tracks",
extractResults: function(json) {
return json.results.data;
},
visitNode: function(node, mappingContext, nodeContext) {
// Had to adjust this so it would lowercase and correctly match
mappingContext.rawValueFn = function(rawEntity, dp) {
name = dp.name;
name.substring(0, 1).toLowerCase() + name.substring(1);
return rawEntity[name];
}
return {
entityType: 'tracks'
};
}
});
首先 ,我建议您查看“手工元数据”主题,该主题描述了使用Breeze Labs元数据帮助程序定义元数据的更简单方法。 这将减少很多单调乏味,使阅读和理解更加清晰。
其次 , 请勿在元数据中指定“jsonResultsAdapter”。 在我看来,就像你将元数据固定到WebAPI适配器一样,事实上,你想要使用另一个。 不要在元数据中指定“namingConvention”,因为这将胜过您在其他地方设置的内容。 并且鉴于您没有从服务器获取元数据,“hasServerMetadata”应该是false
如果你懒得设置它(你不应该)。
第三 ,坚持客户端名称,忘记“nameOnServer”。 无论如何, NamingConvention
将会粉碎。
第四 ,如果(看起来)客户端和服务器端属性名称是两个camelCase 不要更改NamingConvention
默认值! 你不想要任何翻译。 默认不进行翻译。
如果我对此是正确的,请不要将NamingConvention
更改为camelCase! “camelCase”约定告诉Breeze“ 服务器是PascalCase,所以将我的客户端camel case属性名称转换为服务器上的Pascal名称 ”。 如果我理解正确,您不希望客户端“id”成为服务器端“Id”......这将会发生什么。 这就是为什么(我相信)你看到“Id”作为“nameOnServer”。
第五 ,在JsonResultsAdapter
,节点名称与服务器中的JSON匹配,因此是服务器端名称。 保持这种方式。 当NamingConvention将节点属性值转换为实体属性值时,它们会将它们转换为客户端名称。 实际上,如果您错误地在节点上使用客户端名称,您将丢失数据。
当你从服务器到达时,你是否需要改变JSON中的属性名称和值? 如果没有,请不要在visitNode
方法中弄乱这些名称。 关于您需要做的就是确保为节点识别正确的EntityType
并在结果中返回该EntityType
。
第六 ,我很确定visitNode
结果的“entityType”属性必须是实际的EntityType
,而不是您在示例中显示的类型的名称 。 你不能说
return {
entityType: 'tracks',
};
你必须给它真正的类型(我很确定)
return {
entityType: trackType,
};
查看其他Breeze适配器(例如,Web API适配器)。 它从MetadataStore
获取EntityType
。
第七个为什么要设置“nodeId”? 我不是说你做错了。 但你应该知道为什么。 “nodeId”用于在同一实体在有效载荷中多次出现时帮助重建对象图。 只有当某个其他节点中的“nodeRefId”指向“nodeId”值时,它才有用。 此时,只有一种实体而不是关系,设置“nodeId”并不能完成任何事情。 稍后它会......但只有你用一个有意义的值设置它。
我认为您正在做的是将“nodeId”设置为Track
的主键值 。 这不是你的情况下node.id
吗? 如果我是对的, 不要这样做 。 “nodeId” 不是您实体的PK。 它是用循环序列化实体图的标记。
我担心你在这里有点过头了。 编写dataService适配器或jsonResultsAdapter不是Breeze初学者任务。 如果你要去那里,请研究现有的适配器并仔细地遵循它们。 知道为什么他们做他们做的事而不是甩它。
我希望我在这里提供了一些线索。
我怀疑它比你制作它简单得多。 一些关键的想法:
除非确实需要从客户端到服务器更改属性名称的拼写,否则请确保不要更改NamingConvention
。
将JsonResultsAdapter中的“entityType”设置为EntityType
,而不是类型的名称。
不要重写像rawValueFn
这样的breeze函数; 你将打破微风,你不会知道如何或为什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.