Breeze 存在未映射属性的更改问题

Breeze 存在未映射属性的更改问题,breeze,Breeze,在一份报告中,有人指出: “在客户端上,未映射属性在其他方面的行为与映射属性类似” “rejectChanges()将属性还原为原始值” 我遇到了该问题中描述的相同问题:EntityManager.rejectChanges()不会将未映射的属性还原为原始值,而EntityAspect.rejectChanges()会 在对该问题的答复中,有人认为这可能是由于编码错误造成的。我已经就这个问题做了一个论证。我的代码中是否存在导致此问题的错误 编辑-更新的测试用例: test("reje

在一份报告中,有人指出:

  • “在客户端上,未映射属性在其他方面的行为与映射属性类似”
  • “rejectChanges()将属性还原为原始值”
我遇到了该问题中描述的相同问题:EntityManager.rejectChanges()不会将未映射的属性还原为原始值,而EntityAspect.rejectChanges()会

在对该问题的答复中,有人认为这可能是由于编码错误造成的。我已经就这个问题做了一个论证。我的代码中是否存在导致此问题的错误

编辑-更新的测试用例:

    test("reject changes reverts an unmapped property - only unmapped property changed", 1, function () {
        var store = cloneModuleMetadataStore();

        var originalTime = new Date(2013, 0, 1);
        var Customer = function () {
            this.lastTouched = originalTime;
        };

        store.registerEntityTypeCtor("Customer", Customer);

        var manager = newEm(store);

        // create a fake customer
        var cust = manager.createEntity("Customer", { CompanyName: "Acme" },
                   EntityState.Unchanged);
        var touched = cust.lastTouched();

        // we change only the unmapped property (uncomment the next line and the test will pass)
        //cust.CompanyName("Beta");
        cust.lastTouched(new Date(touched.getTime() + 60000));

        //cust.entityAspect.rejectChanges(); // roll back name change
        manager.rejectChanges(); // would have same effect. Obviously less granular

        ok(originalTime === cust.lastTouched(),
            "'lastTouched' unmapped property should be rolled back. Started as {0}; now is {1}"
            .format(originalTime, cust.lastTouched()));
    });
您可以看到,在此环境中,测试通过了entityAspect.rejectChanges(),但失败了manager.rejectChanges()。如果映射属性与未映射属性一起更改,则测试通过。

更新答案2014年2月2日 好的,你发现的其实是设计出来的。和。。感谢上面的测试(它使理解问题变得更容易)

这里的问题是,对未映射属性的更改不会更改实体的EntityState。之所以做出这个决定,是因为这些更改实际上不需要持久化到服务器(因为没有地方放置它们)

第二个问题是,调用EntityManager.rejectChanges时,我们只处理添加、修改或删除了EntityState的实体。由于唯一更改为未映射属性的实体不属于此类别,因此永远不会进行实体级别的rejectChanges调用

有几个变通办法

  • 1) 对未映射属性进行任何更改后,调用EntityAspect.setModified()。您可以在上面的测试中尝试这一点,看看它是否有效。(更复杂的版本是使用EntityManager事件自动执行此操作)
  • 2) 无论何时更改未映射的属性,都要更改任何映射的属性
  • 3) 编写自己的EntityManager.rejectChanges,对EntityManager中的每个实体调用EntityAspect.rejectChanges,而不仅仅是“已更改”的实体。这确实会影响性能,所以我不推荐它,除非你有一个非常小的缓存
请随时提出对您有意义的替代方案。我们已考虑添加设置,以允许您配置对未映射属性的处理。(其中包括未映射的属性更改是否会更改实体状态)


我不能责备这个。。。查看代码时,EntityManager.rejectChanges只需为管理器中的所有实体调用EntityAspect.rejectChanges

所以有两种可能性

1) 您没有看到更改正常工作的EntityAspect实际上没有“附加”到EntityManager

2) 在这两种情况下,您实际上并不是在比较同一实体上的“rejectChanges”行为


查看Breeze zip中DocCode示例中的测试用例。这些测试不需要UI,通常非常简短。如果您可以在这里粘贴一个在该环境中失败的简单测试,我将看一看。有一个用户界面经常会使画面变得模糊

我将在周末尝试看一看这个。我将看一看DocCode示例。不过,有一件事需要澄清:拒绝更改总是与EntityAspect一起正常工作。正是由于EntityManager.rejectChanges()的存在,我没有得到预期的结果。我链接的plunker是一个非常简单的测试用例(非常有限的UI)。我会看看是否能想出一种方法来粘贴一个更简单的测试。注意:breeze.debug.js的第13166行是“if(!this._hasChanges)return[];”。在我的例子中,“this.\u hasChanges”是未定义的,即使我的实体实际上已经更改了(尽管唯一的更改是对unmap属性的更改)。所以,这可以解释为什么它不工作,尽管它只是调用EntityAspect.rejectChanges为所有实体。。。管理器不知道存在任何已更改的实体来调用EntityAspect.rejectChanges。您是否已检查该实体是否附加到EntityManager?。i、 e.aspect.EntityManager!=Null这些实体肯定是附加到管理器的。我用plunker来演示:这是一个屏幕截图,显示了未定义“_hasChanges”的管理器,附加到管理器的实体,以及清晰显示未映射属性的实体,该属性的值与原始值不同: