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; }