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

Ken*_*Ken 5 asp.net-web-api breeze

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

War*_*ard 12

当Breeze将JSON属性数据映射到实体时,它会忽略它无法识别的属性.这就是为什么你的服务器类的计算属性数据被丢弃,即使你在线上的JSON中看到它们.

幸运的是,您可以通过将其注册为未映射的属性来教Breeze识别该属性.我会告诉你如何.让我先介绍一下背景.

背景

如果Breeze客户端是由数据库计算的属性,那么您的计算属性将"已知".数据库支持的属性(常规和计算)在元数据中作为映射属性获取.

但在你的情况下(如果我理解正确),属性是在服务器端类的逻辑中定义的,而不是在数据库中.因此,它不在元数据中的映射属性中.它隐藏在元数据之外.它是一个未映射的实例属性.

我假设你没有把它从序列化器中隐藏起来.如果查看类的查询的网络流量,您可以看到计算出的属性数据到达客户端.问题是当Breeze从这些查询结果中"实现"实体时,它会忽略它.

解决方案举例

解决方案是在MetadataStore中注册计算的属性.

我修改DocCode示例的entityExtensionTests.js以包含此场景; 您可以从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);