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