我通过使用propertyChanged事件向最终用户显示服务器计算值。我使用的是微风1.4.8,我正在使用生产力堆栈(ms sql, web api,等)它工作得很好。最近我更新到1.4.12,我认识到这个事件不再被解雇了。属性"A_ProvisionTotal"只在服务器端计算。
<snip>
var token = vm.transaction.entityAspect.propertyChanged.subscribe(propertyChanged);
function propertyChanged(propertyChangedArgs) {
var propertyName = propertyChangedArgs.propertyName;
if (vm.transaction.tblEmployees.CalculationMethod == "A" && propertyName == "A_ProvisionTotal")
logSuccess('Provision neuberechnet' + '<br/>' + 'Aktuell: ' + $filter('number')(vm.transaction.Provision, 2), true);
</snip>
让我知道如果这是一个已知的回归,如果你需要更多的片段。
关于如何实现所需功能的一些想法。
- 实体可以记住私有字段的最后一次计算值。然后,每当重新计算被触发时,您可以将新值与上次计算值进行比较,如果没有变化,则忽略新计算值。
- 或者,您可以将计算中涉及的属性定义为实体函数中的ES5属性,然后在相关属性的setter中触发计算,当它们被设置为新值时。更多信息请访问:http://www.breezejs.com/documentation/extending-entities#es5-property。如果你想将计算等行为构建到setter中,ES5属性是很方便的。
更新3
这不是一个bug——请参阅对这篇文章的回应,该回复将此描述为一个有文档记录的故意行为。
2014年6月2日更新
我忽略了你问题中的一个关键事实……只有当我看了你在评论中包含的代码后,我才明白了这一点。让我为其他读者摘录其中的关键部分:您的测试发出一个查询,然后将一个不相关的更改保存到服务器(其中感兴趣的属性在服务器端更新),然后检查当保存结果合并回缓存时,该感兴趣的属性是否引发propertyChanged
。
var query = EntityQuery.from("Orders").where('id', 'eq', 10248);
query.using(em).execute().then(querySucceeded).then(checkPropertyChanged).fin(start);
// querySucceed receives order 10248, updates an unrelated property (so you can save),
// wires up a propertyChanged listener and saves, returning the saveChanges promise
function checkPropertyChanged(saveResults) {
var saved = saveResults.entities[0];
// this passes because the server-side change to `Freight` was returned
ok(saved && saved.Freight() === 1200.00,
"freight got changed serverside");
// this fails because Breeze did not notify you that the `Freight` had changed
ok(notifications[0].propertyName === "Freight",
"notified serverside change of Freight Property");
}
总结,你期望在服务器上的属性更改将触发客户端上的propertyChanged
通知,当实体数据作为saveChanges
的副产品从服务器重新检索时。
我写对了吗?
我们的文档没有明确说明合并查询、保存和导入实体结果是否会引发propertyChanged
。
我内部讨论并确认这些操作应该引发propertyChanged
。我还编写了另一个(稍微简单一些)测试,它揭示了您发现的错误:合并保存结果可能不会引发propertyChanged
。
我们有回归测试,显示在v.1.4.12中引发了Breeze EntityAspect.propertyChanged
事件。例如,你可以在DocCode示例"basicTodoTests.js";"中看到它的工作原理。
你能确认这真的是Breeze故障吗?也许您正在更改的属性实际上不是实体属性?有时你认为你正在改变一个实体(例如,你的Transaction
实体),但你改变属性的东西实际上不是一个实体。那么问题是,您认为将映射到Transaction
的数据不是……你可以开始寻找完全不同的问题。
无论如何,我建议你写一个小测试来证实你的怀疑…对你自己来说最重要的是……然后是我们。这将帮助我们发现你们的方案与我们的方案的不同之处。如果你能找到,我们会修好的。谢谢。
实际上,我不确定这是一个bug。属性更改事件确实在保存合并期间被触发,但属性名称参数在保存时被触发时被记录为'null'。
http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html event_propertyChanged
由EntityAspect.propertyChanged:
返回的'propertyName'参数的API文档已更改的属性的名称。对于替换整个实体的操作,此值将为'null'。这包括需要合并的查询、导入和保存。在这种情况下,其余参数也不存在。
在1.4.8和1.4.13之间可能发生的事情是,我们实际上更仔细地实现了我们的设计规范,并可能引入了您的破坏行为。(我们应该这样记录,但很可能遗漏了)。
Ward更新
我更新了DocCode测试,首先确认了你问题中描述的行为,然后确认了记录的行为。
我们很遗憾,我们显然忽略了早期实现文档化的行为,并且我们没有在发布说明(更新后)中提到突破性的更改。
这个测试:
asyncTest("propertyChanged raised when merged save result changes a property", 3, function () {
var em = newTodosEm();
var todo = em.createEntity('TodoItem', {Description: "Saved description" });
em.saveChanges().then(saveSucceeded).catch(handleFail).finally(start);
ok(todo.entityAspect.isBeingSaved, "new todo is in the act of being saved");
// This change should be overwritten with the server value when the save result is returned
// even though the entity is in an Added state and the MergeStrategy is PreserveChanges
// because save expects to merge server values into an entity it is saving
todo.Description("Changed on client before save returns");
var descriptionChanged = false;
todo.entityAspect.propertyChanged.subscribe(function (changeArgs) {
// Watch carefully! The subscription is called twice during merge
// 1) propertyName === "Id" (assigned with permanent ID)
// 2) propertyName === null (WAT?)
// and not called with propertyName === "Description" as you might have thought.
// Actually 'null' means "merged a lot of properties"
// Documented: http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html#event_propertyChanged
// The reason for this: don't want to fire a ton of events on whole entity load
// especially when merging many entities at the same time.
if (changeArgs.propertyName === null || changeArgs.propertyName === 'Description') {
descriptionChanged = true;
}
});
function saveSucceeded(saveResult) {
var saved = saveResult.entities[0];
// passes
equal(saved && saved.Description(), "Saved description",
"the merge after save should have restored the saved description");
// fails
ok(descriptionChanged,
"should have raised propertyChanged after merge/update of 'Description' property");
}
});