breeze rejectChanges未映射属性的问题

时间:2014-01-31 15:53:17

标签: breeze

previous question中,有人说:

  • “在客户端上,未映射的属性在其他方面表现得像映射属性”
  • “rejectChanges()将属性恢复为原始值”

我遇到了该问题中描述的相同问题:EntityManager.rejectChanges()不会将未映射的属性还原为原始值,而EntityAspect.rejectChanges()会这样做。

在对该问题的回答中,有人提出这可能是由于编码错误造成的。我做了一个plunker来证明这个问题。我的代码中是否存在导致此错误的错误?

编辑 - 更新测试用例:

    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()失败。如果映射的属性与未映射的属性一起更改,则测试通过。

1 个答案:

答案 0 :(得分:1)

更新回答2/2/2014

好的,你发现的实际上是设计的。 并且......感谢上面的测试,(这使得理解问题变得更加容易)。

此处的问题是对未映射属性的更改不会更改实体的EntityState。做出这个决定是因为这些更改实际上并不需要持久保存到服务器(因为无处可放)。

第二个问题是,当调用EntityManager.rejectChanges时,我们只处理具有Added,Modified或Deleted EntityState的实体。由于仅对未映射的属性进行ONLY更改的实体不属于此类别,因此永远不会进行实体级别rejectChanges调用。

有几种解决方法。

  • 1)在对未映射的属性进行任何更改后调用EntityAspect.setModified()。您可以在上面的测试中尝试这个,看它是否有效。 (稍微复杂一点的是使用EntityManager事件自动执行此操作)。
  • 2)每当更改未映射的属性时,都要更改任何映射属性。
  • 3)编写自己的EntityManager.rejectChanges,它们对EntityManager中的每个实体调用EntityAspect.rejectChanges,而不仅仅是“已更改”的实体。这确实有性能影响所以我不推荐它,除非你有一个非常小的缓存。

请随意提出一个对您有意义的替代方案。我们已考虑添加设置以允许您配置未映射属性的处理。 (其中包括未映射的属性更改是否会更改实体状态)。


我不能重复这个......并且查看代码,EntityManager.rejectChanges只是调用了经理中所有实体的EntityAspect.rejectChanges。

所以有几种可能性

1)您没有看到rejectChanges正常工作的EntityAspect实际上并未“附加”到EntityManager。

2)在两种情况下,您实际上并没有比较SAME实体上“rejectChanges”的行为。

查看Breeze zip中DocCode示例中的测试用例。这些测试不需要UI,通常很短。如果你可以粘贴一个在那个环境中失败的简单测试,我会看看。涉及到UI通常会使图片变得模糊。