我正在使用BreezeControllerAttribute使用Web API试验BreezeJS。如何公开实体的计算属性?我发现可靠地做到这一点的唯一方法是创建一个继承自实体或使用投影的中间DTO。通常我会在这个场景中使用readonly属性,但这些属性似乎被忽略了。
答案 0 :(得分:12)
当Breeze将JSON属性数据映射到实体时,忽略它无法识别的属性。这就是为什么你的服务器类的计算属性数据被丢弃,即使你在线上的JSON中看到它们。
幸运的是,您可以通过将其注册为未映射的属性来教Breeze识别该属性。我会告诉你如何。让我先介绍一下背景。
如果Breeze客户端是由数据库计算的属性,那么您的计算属性将“已知”。数据库支持的属性(常规和计算)将作为映射属性在元数据中获取。
但是在你的情况下(如果我理解正确的话),属性是在服务器端类的逻辑中定义的,而不是在数据库中定义的。因此,它不在元数据中的映射属性中。它隐藏在元数据之外。它是一个未映射的实例属性。
我假设您没有将其隐藏在序列化程序中。如果查看类的查询的网络流量,您可以看到计算出的属性数据到达客户端。问题是当Breeze从这些查询结果中“实现”实体时,Breeze会忽略它。
解决方案是register the calculated property in the MetadataStore。
我修改了the entityExtensionTests.js of the DocCode sample以包含此方案;您可以从GitHub获取该代码或等待下一个Breeze版本。
或者只需按照以下代码进行操作,从 NorthwindModel.cs 中的Employee
类开始使用此代码段:
// Unmapped, server-side calculated property [NotMapped] // Hidden from Entity Framework; still serialized to the client public string FullName { get { return LastName + (String.IsNullOrWhiteSpace(FirstName)? "" : (", " + FirstName)); } }
以下是 entityExtensionTests.js
中的自动化测试test("unmapped property can be set by a calculated property of the server class", 2, function () { var store = cloneModuleMetadataStore(); // clones the Northwind MetadataStore // custom Employee constructor var employeeCtor = function () { //'Fullname' is a server-side calculated property of the Employee class // This unmapped property will be empty for new entities // but will be set for existing entities during query materialization this.FullName = ""; }; // register the custom constructor store.registerEntityTypeCtor("Employee", employeeCtor); var fullProp = store.getEntityType('Employee').getProperty('FullName'); ok(fullProp && fullProp.isUnmapped, "'FullName' should be an unmapped property after registration"); var em = newEm(store); // helper creates a manager using this MetadataStore var query = EntityQuery.from('Employees').using(em); stop(); // going async query.execute().then(success).fail(handleFail).fin(start); function success(data) { var first = data.results[0]; var full = first.FullName(); // passing test confirms that the FulllName property has a value ok(full, "queried 'Employee' should have a fullname ('Last, First'); it is "+full); } });
您需要做的是在测试示例的这一小部分中:
var yourTypeCtor = function () { this.calculatedProperty = ""; // "" or instance of whatever type is is supposed to be }; // register your custom constructor store.registerEntityTypeCtor("YourType", yourTypeCtor);