繁体   English   中英

返回了EntityTypes中的Breeze EntityQuery缺失数据

[英]Breeze EntityQuery missing data in EntityTypes returned

我正在使用Angular和Breeze建立SPA。 我一直在从复数网站关注John Papa的热巾教程。 我有一个奇怪的问题,我认为可能会从我的元数据产生? 但最后,我并不确定......

首先,我的API正在运行LAMP堆栈,所以我没有使用EF。 我创建了一个元数据端点,我认为它给了我正确的结构。 我正在使用breeze.angular.q.js来帮助我从Q到$ q的映射

资源:api / v1 /元数据

{
    "metadataVersion": "1.0.5",
    "dataServices": [
        {
            "serviceName": "api/v1/",
            "hasServerMetadata": true,
            "jsonResultsAdapter": "webApi_default",
            "useJsonp": false
        }
    ],
    "structuralTypes": [
        {
            "shortName": "tracks",
            "namespace": "MyNamespace",
            "dataProperties": [
                {
                    "name": "id",
                    "nameOnServer": "id",
                    "maxLength": 36,
                    "validators": [],
                    "dataType": "Guid",
                    "isPartOfKey": true
                },
                {
                    "name": "title",
                    "nameOnServer": "title",
                    "maxLength": 255,
                    "validators": [],
                    "dataType": "String"
                },
                {
                    "name": "description",
                    "nameOnServer": "description",
                    "maxLength": 0,
                    "validators": [],
                    "dataType": "String"
                }
            ]
        }
    ]
}

示例API返回数据如下所示:

资源:api / v1 / tracks

{
    "data": [
        {
            "id": "495f21d6-adfc-40b6-a41c-fc93d9275e24",
            "title": "harum",
            "description": "Error doloribus ipsam et sunt fugiat."
        },
        {
            "id": "d7b141d2-6523-4777-8b5a-3d47cc23a0fe",
            "title": "necessitatibus",
            "description": "Voluptatem odit nulla maiores minima eius et."
        }
    ],
    "embeds": [
        "courses"
    ]
}

现在w /我的所有代码,我实际上是从我的api返回正确的数据。 我已经把微风网站上的例子作为我在SO上找到的一些好花絮( 这个问题和来自病房的好答案 )。 唉,没有运气。 基本上发生的事情是当我尝试在我的视图模型中循环我的结果时,从我的微风查询返回,我得到一个角度错误Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: t in vm.tracks, Duplicate key: object:00I Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: t in vm.tracks, Duplicate key: object:00I

调用发生在我的datacontext中的一个函数中。 我的querySucceeded promise回调中返回的数据似乎没有被正确绑定。

datacontext.js

...
function getTrackPartials() {
    ...
    return EntityQuery.from(entityNames.track)
        .toType(entityNames.track)
        .using(manager).execute()
        .then(querySucceeded, _queryFailed);

    function querySucceeded(data) {
        console.log(data);  // <--  Log out to see what is returned
        tracks = data.results;
        _areTracksLoaded(true)
        log('Retrieved [Track Partials] from remote data source', tracks.length, true);
        return tracks;
    }
}

如果我将这些数据记录到控制台,我得到这个(所有的$$ hashKey是相同的,id,title,description都是NULL。但是我得到了正确的结果数,这不是'巧合 - 如果我调整我应该接收的结果数量,它每次都正确匹配)。

querySucceeded promise回调

现在,由于我的数据有点不同 - 我使用了Edmonds示例并创建了一个自定义的JsonResultsAdapter因此我可以“按摩”数据。 目前它非常简陋,因为我只是想让它起作用。 什么真的让我失望,如果我从visitNode中的JsonResultsAdapter函数注销node参数,它有正确的数据.... ???

entityManagerFactory.js

(function () {
    'use strict';

    var serviceId = 'entityManagerFactory';
    angular.module('app').factory(serviceId, ['config', emFactory]);

    function emFactory(config) {
        breeze.config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
        breeze.NamingConvention.camelCase.setAsDefault();

        var serviceName = config.remoteServiceName;
        var metadataStore = new breeze.MetadataStore();

        var provider = {
            metadataStore: metadataStore,
            newManager: newManager
        };

        var jsonResultsAdapter = new breeze.JsonResultsAdapter({
            name: "Tracks",
            extractResults: function(json) {
                console.log(json.results.data);  // <--  Log out to see what is returned
                return json.results.data;
            },
            visitNode: function(node, mappingContext, nodeContext) {
                console.log(node);  // <--  Log out to see what is returned
                return {
                    entityType: 'tracks',
                    nodeId: node.id
                };
            }
        });

        var dataService = new breeze.DataService({
            serviceName: serviceName,
            jsonResultsAdapter: jsonResultsAdapter
        });

        return provider;

        function newManager() {
            var mgr = new breeze.EntityManager({
                dataService: dataService,
                metadataStore: metadataStore
            });

            return mgr
        }
    }
})();

这是我的JsonResultsAdapter :: extractResults函数的返回值 JsonResultsAdapter extractResults返回值

这是我的JsonResultsAdapter :: visitNode函数中的一个节点 JsonResultsAdapter visitNode节点参数

任何帮助,将不胜感激。 就像我说的,我不确定错误发生在哪里? 但是,如果我不得不猜测,我会说我的EntityQuery使用我的经理和JsonResultsAdapter之间存在一些脱节,这可能是由我生成的错误元数据引起的。

** 更新 **

所以我浏览了微风代码,找出了我丢失数据的地方,并且能够弄清楚最新情况和解决方法。 但是,我不确定这是否是实际处理此问题的最佳方法。

我应该提一下,我用凉亭来安装微风 - 通过这样做我去了bower-breeze-angular git://github.com/eggers/bower-breeze-angular.git包而不是默认的微风breeze git://github.com/IdeaBlade/Breeze.git随着示例和其他数据而膨胀,我并不热衷于打包到我的回购中。

在微风中,在我的JsonResultsAdapter::visitnode回调返回之后,它需要“ 合并 ”我的数据,我遇到的问题是从我的节点返回的entityKey不匹配。 这是因为rawValueFn从我mappingContext正在寻找nameOnServer ,我认为我在从我的服务器我的元数据集-但不知何故,当我登录了我的dataproperty它已经从我的设置改变。

这是一个dp注销,如果你回顾我的元数据资源调用中的顶部,我特意将其设置为“id”。 这是如何改变为Id的? 那是什么导致我的头痛!

DataProperty已更改nameOnServer密钥

我可以通过在我的JsonResultsAdapter中的mappingContext上更新我的rawValueFn函数来解决这个JsonResultsAdapter ,一切都会起作用 - 但这感觉就像是“黑客”。 我也试过玩“NamingConvention”,但这似乎也不起作用。

这是我更新的JsonFactory,它使它工作

    var jsonResultsAdapter = new breeze.JsonResultsAdapter({
        name: "Tracks",
        extractResults: function(json) {
            return json.results.data;
        },
        visitNode: function(node, mappingContext, nodeContext) {

            // Had to adjust this so it would lowercase and correctly match
            mappingContext.rawValueFn = function(rawEntity, dp) {
                name = dp.name;
                name.substring(0, 1).toLowerCase() + name.substring(1);
                return rawEntity[name];
            }

            return {
                entityType: 'tracks'
            };
        }   
    }); 

哇这是一个很长的问题。

首先 ,我建议您查看“手工元数据”主题,该主题描述了使用Breeze Labs元数据帮助程序定义元数据的更简单方法。 这将减少很多单调乏味,使阅读和理解更加清晰。

其次请勿在元数据中指定“jsonResultsAdapter”。 在我看来,就像你将元数据固定到WebAPI适配器一样,事实上,你想要使用另一个。 不要在元数据中指定“namingConvention”,因为这将胜过您在其他地方设置的内容。 并且鉴于您没有从服务器获取元数据,“hasServerMetadata”应该是false如果你懒得设置它(你不应该)。

第三 ,坚持客户端名称,忘记“nameOnServer”。 无论如何, NamingConvention将会粉碎。

第四 ,如果(看起来)客户端和服务器端属性名称是两个camelCase 不要更改NamingConvention默认值! 你不想要任何翻译。 默认不进行翻译。

如果我对此是正确的,请不要NamingConvention更改为camelCase! “camelCase”约定告诉Breeze“ 服务器是PascalCase,所以将我的客户端camel case属性名称转换为服务器上的Pascal名称 ”。 如果我理解正确,您不希望客户端“id”成为服务器端“Id”......这将会发生什么。 这就是为什么(我相信)你看到“Id”作为“nameOnServer”。

第五 ,在JsonResultsAdapter ,节点名称与服务器中的JSON匹配,因此是服务器端名称。 保持这种方式。 当NamingConvention将节点属性值转换为实体属性值时,它们会将它们转换为客户端名称。 实际上,如果您错误地在节点上使用客户端名称,您将丢失数据。

当你从服务器到达时,你是否需要改变JSON中的属性名称和值? 如果没有,请不要在visitNode方法中弄乱这些名称。 关于您需要做的就是确保为节点识别正确的EntityType并在结果中返回该EntityType

第六 ,我很确定visitNode结果的“entityType”属性必须是实际的EntityType ,而不是您在示例中显示的类型的名称 你不能说

return {
   entityType: 'tracks',
};

你必须给它真正的类型(我很确定)

return {
   entityType: trackType,
};

查看其他Breeze适配器(例如,Web API适配器)。 它从MetadataStore获取EntityType

第七个为什么要设置“nodeId”? 我不是说你做错了。 但你应该知道为什么。 “nodeId”用于在同一实体在有效载荷中多次出现时帮助重建对象图。 只有当某个其他节点中的“nodeRefId”指向“nodeId”值时,它才有用。 此时,只有一种实体而不是关系,设置“nodeId”并不能完成任何事情。 稍后它会......但只有你用一个有意义的值设置它。

我认为您正在做的是将“nodeId”设置Track主键值 这不是你的情况下node.id吗? 如果我是对的, 不要这样做 “nodeId” 不是您实体的PK。 它是用循环序列化实体图的标记。

哇,我的答案很长

我担心你在这里有点过头了。 编写dataService适配器或jsonResultsAdapter不是Breeze初学者任务。 如果你要去那里,请研究现有的适配器并仔细地遵循它们。 知道为什么他们做他们做的事而不是甩它。

我希望我在这里提供了一些线索。

我怀疑它比你制作它简单得多。 一些关键的想法:

  • 除非确实需要从客户端到服务器更改属性名称的拼写,否则请确保不要更改NamingConvention

  • 将JsonResultsAdapter中的“entityType”设置为EntityType ,而不是类型的名称。

  • 不要重写像rawValueFn这样的breeze函数; 你将打破微风,你不会知道如何或为什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM