使用微风js和web api处理计算属性 [英] Handling calculated properties with breezejs and web api

查看:20
本文介绍了使用微风js和web api处理计算属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

当 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 MetadataStore//自定义员工构造函数var employeeCtor = 函数 () {//'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 = function () {this.calculatedProperty = "";//"" 或任何类型的实例应该是};//注册你的自定义构造函数store.registerEntityTypeCtor("YourType", yourTypeCtor);

I'm experimenting with BreezeJS with Web API using the BreezeControllerAttribute. How should calculated properties on an entity be exposed? The only way I've found to do this reliably is to create an intermediate DTO that inherits from the entity or use a projection. Normally I would use a readonly property for this scenario, but those appear to be ignored.

解决方案

When Breeze maps JSON property data to entities, it ignores properties that it does not recognize. That's why your server class's calculated property data are discarded even though you see them in the JSON on the wire.

Fortunately, you can teach Breeze to recognize the property by registering it as an unmapped property. I'll show you how. Let me give some background first.

Background

Your calculated property would be "known" to the Breeze client had it been a property calculated by the database. Database-backed properties (regular and calculated) are picked up in metadata as mapped properties.

But in your case (if I understand correctly) the property is defined in the logic of the server-side class, not in the database. Therefore it is not among the mapped properties in metadata. It is hidden from metadata. It is an unmapped instance property.

I assume you're not hiding it from the serializer. If you look at the network traffic for a query of the class, you can see your calculated property data arriving at the client. The problem is that Breeze is ignoring it when it "materializes" entities from these query results.

Solution with example

The solution is to register the calculated property in the MetadataStore.

I modified the entityExtensionTests.js of the DocCode sample to include this scenario; you can get that code from GitHub or wait for the next Breeze release.

Or just follow along with the code below, starting with this snippet from the Employee class in NorthwindModel.cs:

// 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)); }
}

And here is the automated test in 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);
    }

});

What you need to do is in this small part of the test example:

var yourTypeCtor = function () {
    this.calculatedProperty = ""; // "" or instance of whatever type is is supposed to be
};

// register your custom constructor
store.registerEntityTypeCtor("YourType", yourTypeCtor);

这篇关于使用微风js和web api处理计算属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆