【发布时间】:2013-08-02 15:26:45
【问题描述】:
我正在使用 BreezeControllerAttribute 对带有 Web API 的 BreezeJS 进行试验。应如何公开实体上的计算属性?我发现可靠地做到这一点的唯一方法是创建一个从实体继承的中间 DTO 或使用投影。通常我会在这种情况下使用只读属性,但这些似乎被忽略了。
【问题讨论】:
我正在使用 BreezeControllerAttribute 对带有 Web API 的 BreezeJS 进行试验。应如何公开实体上的计算属性?我发现可靠地做到这一点的唯一方法是创建一个从实体继承的中间 DTO 或使用投影。通常我会在这种情况下使用只读属性,但这些似乎被忽略了。
【问题讨论】:
当 Breeze 将 JSON 属性数据映射到实体时,它会忽略它无法识别的属性。这就是为什么您的服务器类的计算属性数据被丢弃的原因,即使您在线上的 JSON 中看到它们也是如此。
幸运的是,您可以通过将其注册为未映射的属性来教 Breeze 识别该属性。我会告诉你怎么做。让我先介绍一些背景。
如果您计算的属性是由数据库计算的属性,那么 Breeze 客户端将“知道”它。数据库支持的属性(常规属性和计算属性)在元数据中作为映射属性获取。
但在您的情况下(如果我理解正确的话)该属性是在服务器端类的逻辑中定义的,而不是在数据库中。因此,它不在元数据中的映射属性中。它对元数据隐藏。它是一个未映射的实例属性。
我假设您没有对序列化程序隐藏它。如果您查看类查询的网络流量,您可以看到您计算的属性数据到达客户端。问题是 Breeze 在从这些查询结果中“具体化”实体时忽略了它。
解决办法是register the calculated property in the MetadataStore。
我修改了the entityExtensionTests.js of the DocCode sample 以包含这个场景;您可以从 GitHub 获取该代码或等待下一个 Breeze 版本。
或者只是跟随下面的代码,从 NorthwindModel.cs 中的 Employee 类中的这个 sn-p 开始:
这是 entityExtensionTests.js
中的自动化测试 test("未映射的属性可以由服务器类的计算属性设置", 2, 功能 () { var store = cloneModuleMetadataStore(); // 克隆 Northwind 元数据存储 // 自定义员工构造函数 varemployeeCtor = 函数 () { //'Fullname' 是 Employee 类的服务器端计算属性 // 对于新实体,这个未映射的属性将为空 // 但将在查询具体化期间为现有实体设置 this.FullName = ""; }; // 注册自定义构造函数 store.registerEntityTypeCtor("Employee", employeeCtor); var fullProp = store.getEntityType('Employee').getProperty('FullName'); 好的(fullProp && fullProp.isUnmapped, "'FullName' 应该是注册后未映射的属性"); var em = newEm(store); // helper 使用这个 MetadataStore 创建一个管理器 var query = EntityQuery.from('Employees').using(em); 停止(); // 异步 query.execute().then(success).fail(handleFail).fin(start); 功能成功(数据){ var first = data.results[0]; var full = first.FullName(); // 通过测试确认 FulllName 属性有值 ok(full, "查询的'Employee'应该有一个全名('Last, First');它是"+full); } });你需要做的是在这个小部分的测试示例中:
var yourTypeCtor = 函数 () { this.calculatedProperty = ""; // "" 或任何类型的实例应该是 }; //注册你的自定义构造函数 store.registerEntityTypeCtor("YourType", yourTypeCtor);【讨论】:
NamingConvention。这是一个非常简单的 API,编写自定义 NamingConvention 正是我们希望/期望您在您所描述的情况下做的事情。