Breeze &引用;密钥修复中出现内部错误-无法定位实体“0”;错误,但数据库已按预期更新
我正在努力调试这个错误,因为尽管一直有报告,但应用程序的行为与预期一致。如果您能给我指点一下它的含义以及我如何调试它的源代码,我将不胜感激 抱歉说得含糊不清,但由于我得到了预期的结果,我不确定还需要提供哪些信息 更新Breeze &引用;密钥修复中出现内部错误-无法定位实体“0”;错误,但数据库已按预期更新,breeze,Breeze,我正在努力调试这个错误,因为尽管一直有报告,但应用程序的行为与预期一致。如果您能给我指点一下它的含义以及我如何调试它的源代码,我将不胜感激 抱歉说得含糊不清,但由于我得到了预期的结果,我不确定还需要提供哪些信息 更新 我已经为这个问题创建了一个副本,并试图将代码集中在这个问题上。即使数据库已正确更新,也会持续引发错误。代码中只有一个saveChanges,它使用Breeze Todo示例中dataservice.js中的save功能。SaveOptions.allowConcurrentSave
我已经为这个问题创建了一个副本,并试图将代码集中在这个问题上。即使数据库已正确更新,也会持续引发错误。代码中只有一个saveChanges,它使用Breeze Todo示例中dataservice.js中的save功能。SaveOptions.allowConcurrentSaves为false 完全不知所措地解释它,并且已经查看了我的EF代码,看看我是否犯了一个明显的错误,但看不到它。发送到WebAPI SaveChanges方法的包看起来也正确(正确填充了ID等) 2月6日更新 韦德的有益回答仍然没有解决这个问题。不幸的是,除非我能理解我做错了什么,或者知道这是一个bug,否则我将不得不放弃在这个项目中使用Breeze,转而使用蹩脚、简单的AJAX调用 问题似乎围绕着服务器在保存更改时返回归零的GUID。该方法不返回任何错误。当我得知这是我实体模型中的一个bug时,我会非常激动,但我对此表示怀疑 以下是失败的原因: breeze.debug.js:11954
var ix = this._indexMap[tempValue];
if (ix === undefined) {
throw new Error("Internal Error in key fixup - unable to locate entity");
}
当代码到达这一点时,this.\u indexMap的值正确且为:
{"bcb6e670-00fc-469d-8531-5767f40bf3c1":0}
1093b975-7686-4621-8336-77c38ed36de0
但是tempValue的值(由服务器从Web API调用返回)是错误的:
00000000-0000-0000-0000-000000000000
realValue是正确的,并且是:
{"bcb6e670-00fc-469d-8531-5767f40bf3c1":0}
1093b975-7686-4621-8336-77c38ed36de0
备份堆栈。下面是AJAX调用breeze.debug.js:12574的结果。请确保从服务器/WebAPI调用返回时tempValue为零。realValue是正确的。这就是数据库包含的内容。该行被毫无问题地添加到表中
"KeyMappings": [
{
"$id": "4",
"$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
"EntityTypeName": "...Score",
"TempValue": "51877f5b-811f-4260-bd5b-cf9965159597",
"RealValue": "92b73b8a-8b33-45cd-9822-ca7c0c5d5d9a"
},
{
"$id": "5",
"$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
"EntityTypeName": "...PropertyValue",
"TempValue": "00000000-0000-0000-0000-000000000000",
"RealValue": "1093b975-7686-4621-8336-77c38ed36de0"
}
],
根据saveBundle中服务器端接收到的内容进行验证。注意:在服务器上接收到的两个实体的ID都具有有效的GUID ID
"entities": [
{
"ID": "51877f5b-811f-4260-bd5b-cf9965159597",
...
"entityAspect": {
"entityTypeName": "Score:...",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": {
"propertyName": "ID",
"autoGeneratedKeyType": "Identity"
}
}
},
{
"ID": "bcb6e670-00fc-469d-8531-5767f40bf3c1",
...
"entityAspect": {
"entityTypeName": "PropertyValue:...",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": {
"propertyName": "ID",
"autoGeneratedKeyType": "Identity"
}
}
}
],
毫不奇怪,在breeze.debug.js:10494 saveBundleStringified中创建的AJAX调用发送到服务器的值是正确的,并且与服务器接收到的值相同(不会重现,但我向您保证它们是正确的)
根据我的代码,当调用saveChanges时
manager.getChanges().length == 2
manager.getChanges()[0].ID() == "51877f5b-811f-4260-bd5b-cf9965159597" (Score)
manager.getChanges()[1].ID() == "bcb6e670-00fc-469d-8531-5767f40bf3c1" (PropertyValue)
而且,正如预期的那样,它们与服务器接收到的saveChanges期间实体ID的(temp)值相匹配
我做错了什么??如果我有头发,我会把它撕下来 当多个同时挂起的保存请求同时都涉及密钥生成时,可能会发生此错误。此错误是否仅在保存期间发生?如果是,请尝试将SaveOptions.allowConcurrentSaves设置为false。如果这导致了不同的错误(并发保存错误),那么您的问题肯定与并发保存有关 希望这能有所帮助。1月27日更新: 根据您对Sergey答案的评论,在保存操作完成之前,您可能一直在尝试对更改的实体执行某些操作 这些实体仍处于更改状态。。。通常使用临时主键和外键。。。直到服务器报告成功保存为止 在保存成功之前,您可能不应该触摸它们。正如Sergey所观察到的,您应该在save success回调中找到保存后处理 return manager.saveChanges() .then(saveSucceeded) .fail(saveFailed); 并发保存 我注意到,在您的代码中,您正在使用在Todo示例中找到的防止非法并发保存 这种方法实际上只适用于演示。如果您的视图模型在保存成功时需要执行某些任务,那么它根本不适用于您。这将不起作用,因为dataservice无法使用延时方法向视图模型返回承诺 如果需要非阻塞保存,请查看“Cool Breezes”部分“”主题中描述的“”插件 简洁地创建实体 在查看代码时,我忍不住注意到scoreissue.1.0.ts中的实体工厂方法有点冗长。你写的是: export function Business(manager, o: IBusiness) { var business = manager.metadataStore.getEntityType("Business").createEntity(); business.ID(breeze.core.getUuid()); business.Name(o.name); manager.addEntity(business); return business; } 出口职能业务(经理,o:IBusiness){ var business=manager.metadataStore.getEntityType(“业务”).createEntity(); business.ID(breeze.core.getUuid()); 企业名称(o.Name); 增编(业务)经理; 退货业务; } 可以简单到: export function Business(manager, o: IBusiness) { return manager.createEntity("Business", { ID: breeze.core.getUuid(), Name: o.name, }); } 出口职能业务(经理,o:IBusiness){ return manager.createEntity(“业务”{ ID:breeze.core.getUuid(), 姓名:o.Name, }); }
EntityManager.createEntity
快捷方式是新的,因为您编写了此代码,所以错过它也不必感到难过
原始答复:
[错误的方向。保留以理解DazWilkin的评论,即问题出在客户身上。]
这是在哪里生成的?在服务器上?如果是这样,您可以将EFContextProvider子类化并覆盖
SaveChangesCore
。调用base.SaveChangesCore
并在其周围放置try/catch。检查saveMap
参数。EFContextProvider是开源的;我会从这里开始挖掘。我也有同样的问题,我已经在jQuery对象的帮助下解决了这个问题。我的dataservice保存方法现在如下所示:
saveChanges = function () {
var def = $.Deferred();
if (manager.hasChanges()) {
manager.saveChanges()
.then(function () { def.resolve() })
.fail(function (error) {
handleSaveError(error);
def.reject();
});
} else {
logger.info("Nothing to save");
def.resolve();
};
return def.promise();
};
我也使用jQuery延迟对象从视图模型中调用它:
$.when(dataservice.saveChanges())
.done(function () {
...some actions
})
我已经解决了
我不一致应用的(!)约定是将setter设置为代码优先类型的内部/私有。我说的前后不一致是因为,在感觉我已经用尽了所有可能之后,我发现PropertyValue类型,即引发错误的类型,有一个内部集合
删除此项并重新构建解决方案后,问题就解决了
所以:public Guid ID { get; set; }