【问题标题】:Breeze creates duplicate entity in local cache after saving to serverBreeze 保存到服务器后在本地缓存中创建重复实体
【发布时间】:2014-04-10 22:51:36
【问题描述】:

我遇到了与New Breeze 1.4.9 - Duplicate entity - possible bug? 中描述的相同的问题,但是据报告该问题是由修复后的错误引起的。我正在使用 v1.4.11。

我发现当我将一个新的 Breeze 实体保存到服务器时,它会通过创建一个新的、重复的实体而不是更新现有的实体来响应来自服务器的成功响应。我在浏览器控制台中逐行运行以下测试代码,处于 Breeze 缓存中没有实体的状态。

EntityManager.createEntity("CustomGroup", properties);
EntityManager.getChanges(); =>
    0:
        Id="b0cb3194-35af-4d23-9e77-d192c907b566"
        EntityState=Added

到目前为止,一切都很好。正如预期的那样,挂起的更改数组中有一个实体。

EntityManager.saveChanges(); =>
    KeyMappings:
        0:
            TempValue="b0cb3194-35af-4d23-9e77-d192c907b566"
            RealValue="f056f519-9f11-4375-a0dd-5272a11b9b46"

执行 saveChanges() 后,服务器返回一个 KeyMapping 对象,其中包含 temp 和 real key 值。此时,列出缓存中的所有实体会发现一个意想不到的结果:

EntityManager.getEntities(); =>
    0:
        Id="f056f519-9f11-4375-a0dd-5272a11b9b46"
        EntityState=Added
    1:
        Id="b0cb3194-35af-4d23-9e77-d192c907b566"
        EntityState=Unchanged

因此,虽然 Breeze 已将原始对象的状态更改为“未更改”以响应保存到服务器,但它并未使用新密钥对其进行更新,而是使用新密钥创建了一个重复实体,它认为它仍然需要保存。

第二次调用 saveChanges() 向服务器发送一个新请求,该请求以具有相同 TempValue 和 RealValue 的 KeyMapping 对象进行响应,此时 Breeze 决定不再进行更改,尽管流氓实体仍在当然是缓存。

【问题讨论】:

  • 您能否使用其中一种 DocCode 模型(在 Breeze + Samples zip 中找到)创建一个重现单元测试?到目前为止,我无法重现您的问题。
  • 我无法用 DocCode 示例复制问题,但我在这里整理了一个非常简单的演示:dl.dropboxusercontent.com/u/13860553/breeze-test.rar。只需通过本地 Web 服务器运行它。我已经为元数据放入静态 JSON 文件并模拟来自 SaveChanges 的响应;这两个都是从我从完整的 .NET Web API 项目中获得的真实服务器响应中复制的。单击链接会将相关对象和详细信息记录到浏览器控制台,以显示在创建实体并将该实体保存到服务器之前和之后 Breeze 缓存发生的情况。

标签: breeze


【解决方案1】:

我查看了您的 Metadata.json,我认为问题就在那里。 OData 元数据有时无法提供足够的信息。在这种情况下,我认为 Breeze 客户端不知道 ContentGroup 具有自动生成的密钥。

我们通常建议在服务器上使用 WebApi Breeze ContextProvider 和 BreezeControllerAttribute 而不是 OData。更多原因请参见Breeze Documentation

【讨论】:

  • 我们很早就遇到了自动生成密钥的问题,所以我们在 dataservice.js 中有这段代码来在客户端设置它:var types = metadataStore.getEntityTypes(); for(var i in types){ types[i].autoGeneratedKeyType = breeze.AutoGeneratedKeyType.Identity; } 所以我不认为这是问题。 (我注意到我不小心在示例代码中将此注释掉了,但我只是再次检查它是否处于活动状态)。顺便说一句,我们已经在使用 Web API Breeze ContextProvider 和 BreezeControllerAttribute,所以我们不确定为什么必须设置 autoGeneratedKeyType。
  • 啊,对不起。如果您使用 Code First,我认为您需要在您的 Id 属性上添加注释:[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 以使其出现在元数据中。
  • 太好了,谢谢史蒂夫,这似乎可以解决问题。不过,我们仍然遇到重复实体问题。
【解决方案2】:

好的,我想通了。服务器在 SaveChanges 的响应中返回的实体具有临时键值,而它应该具有新的服务器生成的值。我注意到了这一点,但认为这是正确的行为,Breeze 在收到响应后会使用 KeyMapping 对其进行整理。

我在 Breeze.ContextProviderEF6.EFContextProvider.cs 中看不到任何修改提交实体的键值的东西,所以这可能是在 EntityFramework 中自动发生的事情,但我们需要在我们的自定义 LightSpeed ContextProvider 中手动完成.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 2013-12-10
    • 2022-01-20
    相关资源
    最近更新 更多