使用breezejs和web api处理计算的属性

时间:2013-05-13 14:06:20

标签: breeze asp.net-web-api

我正在使用BreezeControllerAttribute使用Web API试验BreezeJS。如何公开实体的计算属性?我发现可靠地做到这一点的唯一方法是创建一个继承自实体或使用投影的中间DTO。通常我会在这个场景中使用readonly属性,但这些属性似乎被忽略了。

1 个答案:

答案 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);