对象extraMetadata
未定义,并在breeze.labs.dataservice.sharepoint.js
rawEntity.__metadata = { 'type': aspect.extraMetadata.type };
我怀疑是因为我没有在我的实体定义中定义__metadata
对象中找到的类型。关于如何正确定义我的类型的任何建议都将非常受欢迎!这是我对其中一个对象的类型定义。
models.Project = {
name: 'Project',
defaultResourceName: 'getbytitle(\'Projects\')/items',
dataProperties: {
ID: {
type: breeze.DataType.Int32
},
Title: {
nullable: false
},
StatusId: {
type: breeze.DataType.Int32,
nullable: false
},
SelectedApproverId: {
type: breeze.DataType.Int32,
nullable: false
},
Created: {
type: breeze.DataType.DateTime
},
Modified: {
type: breeze.DataType.DateTime
}
},
navigationProperties: {
Status: {
type: "Status",
foreignKeyNames: ['StatusId'],
hasMany: false
},
SelectedApprover: {
type: "User",
foreignKeyNames: ["SelectedApproverId"]
}
}
};
更新日期:2013年11月11日
如果我运行以下查询:
return breeze.EntityQuery
.from(metadataStore.getEntityType('Project').defaultResourceName)
.orderBy('Created desc')
.using(manager)
.execute()
.then(function (data) {
console.log(data.results);
return data.results;
});
结果是一组简单的JavaScript对象,而不是Breeze Entities,缺少__metadata
属性。我试图弄清楚为什么会这样。
更新:2014年11月12日
我已经确认,当我在navigationProperties
下定义了多个实体时会出现此问题。
答案 0 :(得分:3)
请确保您使用的是BreezeJS v.1.4.12或更高版本。
要明确的是,您所引用的代码位于我所拥有的 breeze.labs.dataservice.sharepoint.js 文件的第147行(而不是247) 。
它位于{{1>} 准备保存修改后的实体。我假设您已查询_createChangeRequest
实体,对其进行了更改,并在发生错误时将其保存。
我认为问题不会追溯到您为Product
类型定义元数据的方式。
您不应为您的类型定义Product
属性。当您查询实体的OData源时,__metadata
属性是我们期望SharePoint(实际上是任何OData源)添加到它发送给客户端的JSON实体数据。
__metadata
不会针对投影返回的结果进行定义,但是您的问题涉及已修改的实体,所以我假设您通过普通查询获取了此实体。一个没有__metadata
条款的人。
我想知道您是否在检索到您正在修改的实体的查询的JSON有效内容中看到select
属性。请检查查询请求中的网络流量。如果您没有在那里看到它,我们必须找出服务器没有发送它的原因。
JSON节点上的__metadata
属性是与SharePoint OData服务器签订合同的关键部分。这就是Breeze客户了解实体类型及其标签的方式。
查看__metadata
和jsonResultsAdapter.visitNode
方法。您将看到适配器如何使用updateEntityNode
来确定该数据的__metadata
。您还将看到适配器将EntityType
移动到适配器结果的__metadata
属性。随后,BreezeJS将“额外元数据”从此结果对象移动到实体的extraMetadata
属性。
这似乎受到了折磨吗? 被折磨。 OData需要与实体(特别是etag)一起携带的额外信息,否则服务器不会更新或删除实体。我们必须将这些信息从头发中松散,然后在我们向服务器发出保存请求时将其恢复。我们把它放在entityAspect.extraMetadata
上,以保持该属性作为“实体”的守护者的角色,该角色与您的对象的业务目的无关以及与其如何关联坚持不懈。
为什么。错误在哪里?
底层错误是来自SharePoint OData源的entityAspect
消失了。我们还不知道它是如何消失的。但如果没有它,我们就会遇到大麻烦。
当缺少__metadata
时,sharepoint适配器应该提供更好的消息。我们实际上在几行之后寻找那个问题;见extraMetadata
:
adjustUpdateDeleteRequest
该测试显得为时已晚。我会做一个注释来推动测试。
但是这样的修复只会导致保存因更好的消息而失败。它不会告诉你如何解决它。
让我们努力找到var extraMetadata = aspect.extraMetadata;
if (!extraMetadata) {
throw new Error("Missing the extra metadata for an update/delete entity");
}
消失的地方......首先是它是否已经到达。
我在等你的报告。
我还在等待您是否在原始实体查询的响应中看到__metadata
属性。
与此同时,我检查了OData规范(复数)以获取对__metadata
属性的引用。似乎__metadata
属性始终是可选的。因此,OData提供商不需要发送或尊重etag ......我们知道这是可能的,因为Web API 2 OData不支持etags ......一个很快就会被纠正的缺陷。
See the OData v.2 spec where it describes JSON format。搜索术语“__metadata”。
OData v.3规范还在JSON响应中调用
__metadata
属性(至少是JSON详细响应)。但......重重叹息......看来
__metadata
属性已从v.4规范中消失,元数据信息完全通过JSON注释提供。 DataJS库(由许多但不是所有BreezeJS OData适配器使用)可以将这些注释映射到节点的__metadata
属性中,但我还无法确认。我们有一些工作要做,以应对所有这些变化。
与此同时,我认为所有BreezeJS OData数据服务适配器应该对额外的元数据采取更具防御性的立场,并且应该忽略遗漏而不是抛出异常。
我们很快就会做出这些防御性改变。
当然,如果OData服务实际上需要etag或其他元数据,服务器将拒绝您的更新或删除请求。我不知道我们能做些什么。
答案 1 :(得分:3)
暂时还没有发帖,但我将分享我发现的问题以及我是如何为我解决的(因为我花了很长时间)。
基本上breeze.labs.dataservice.sharepoint
适配器有一个函数serverTypeNameToClientDefault()
,它需要__metadata"类型"中REST/OData
返回的SharePoint自定义列表类型。字段为完全格式:
SP.Data.**mylistname**sListItem** (notice the "sListItem" suffix; ; Ex. SP.Data.CustomersListItem)
此函数执行字符串正则表达式以从SharePoint类型中提取Breeze实体名称,并使用该名称在元数据存储中查找实体("客户"在上例中)。如果没有匹配,Breeze将找不到您的实体,并将返回基本对象而不是Breeze实体。因此,从SharePoint返回您的REST JSON结果,即使它确实没有将__metadata属性转换为包含属性entityAspect.extraMetadata
的Breeze实体等。这就是导致错误的原因" 无法获得属性'类型'未定义或空引用"
对于我的解决方案,因为在我的情况下,我并不关心我的自定义列表的URL是什么,我只是确保当我的自定义列表由SharePoint配置时,它导致了一个名称根据微风所期待的。您可以通过设置Url
元素的ListInstance
属性来完成此操作:
<ListInstance
Title="My Customers"
OnQuickLaunch="TRUE"
TemplateType="10000"
Url="Lists/Customers" <!-- List/Customer will not work -->
Description="My List Instance">
...
更好的解决方案是使serverTypeNameToClientDefault()
函数更强大或在本地修复它的需求,但希望这可以在适配器的未来版本中解决。
请注意,我已使用以下配置(未列出所有依赖项)测试此解决方案:
Breeze.Client 1.4.9 with Breeze.DataService.SharePoint 0.2.3
Breeze.Client 1.5.0与Breeze.DataService.SharePoint 0.3.2
另请注意,如上所述,0.3.2版本的适配器现在会显示更好的错误消息 - &#34; 缺少更新/删除实体的额外元数据& #34 ;;但它并没有解决问题。
希望这有助于某人。
答案 2 :(得分:2)
对于breeze v1.4.14和breeze labs sharepoint 2013 v0.2.3我在文件 breeze.labs.dataservice.sharepoint.js 中使用小修补程序。 在功能结束时
function visitNode(node, mappingContext, nodeContext)
之前
return result;
我只是像这样设置属性extraMetadata:
result.extraMetadata = node.__metadata;
当我尝试将修改后的实体保存回sharepoint时,这似乎解决了问题。
答案 3 :(得分:2)
对于这个姗姗来迟的方面,我们很抱歉,但是今天解决了额外“s”的错误......最后。您可以在此处跟踪问题:https://github.com/andrewconnell/breeze.js.labs/issues/6
这一切都源于我做出的一个非常不正确的假设。它已在SharePoint数据服务适配器的0.6.2版中得到修复。请注意,在元数据存储中创建实体时,必须使用与实体相同的名称作为数据来源的列表。
答案 4 :(得分:0)
我通过修改navigationProperties
breeze.labs.dataservice.sharepoint.js v.0.10.0
的问题
我改变了:
if (entityType._mappedPropertiesCount <= Object.keys(node).length - 1)
为:
if (entityType.dataProperties.length <= Object.keys(node).length - 1)
_mappedPropertiesCount
似乎也包含navigationProperties
计数。例如dataProperties.length + navigationProperties.length
然后认为查询节点不包含实体的完整属性集(假设它是部分投影的结果)。
因此,它没有被视为一个实体,它的元数据没有被设置,并且它最终没有被添加到缓存中。由于navigationProperty
,__元数据和ID中有两个额外项目,因此只使用了一个Object.keys(node)
。所以它仍会通过一个navigationProperty
而不是两个或更多的测试通过测试。