我正在使用 BreezeControllerAttribute 对带有 Web API 的 BreezeJS 进行试验。应如何公开实体上的计算属性?我发现可靠地做到这一点的唯一方法是创建一个从实体继承的中间 DTO 或使用投影。通常我会在这种情况下使用只读属性,但这些似乎被忽略了。
1 回答
当 Breeze 将 JSON 属性数据映射到实体时,它会忽略它无法识别的属性。这就是为什么您的服务器类的计算属性数据被丢弃,即使您在线上的 JSON 中看到它们。
幸运的是,您可以通过将其注册为未映射的属性来教 Breeze 识别该属性。我会告诉你怎么做。让我先介绍一些背景。
背景
如果您计算的属性是由数据库计算的属性,那么 Breeze 客户端将“知道”它。数据库支持的属性(常规的和计算的)在元数据中作为映射属性被拾取。
但是在您的情况下(如果我理解正确的话),该属性是在服务器端类的逻辑中定义的,而不是在数据库中。因此,它不在元数据中的映射属性中。它对元数据隐藏。它是一个未映射的实例属性。
我假设您没有将其隐藏在序列化程序中。如果您查看类查询的网络流量,您可以看到您计算的属性数据到达客户端。问题是 Breeze 在从这些查询结果中“具体化”实体时忽略了它。
示例解决方案
解决方案是在 MetadataStore 中注册计算的属性。
我修改了DocCode示例的 entityExtensionTests.js以包含此场景;您可以从 GitHub 获取该代码或等待下一个 Breeze 版本。
或者只是跟随下面的代码,从NorthwindModel.csEmployee
类的这个片段开始:
// 未映射的,服务器端计算的属性 [NotMapped] // 从实体框架中隐藏;仍然序列化到客户端 公共字符串全名 { 获取{返回姓氏+ (String.IsNullOrWhiteSpace(FirstName)? "" : (", " + FirstName)); } }
这是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);