Daniel Oliveira
Daniel Oliveira

Reputation: 1

Problems when map breeze entities from dto after a query using expand

Every time I try to map a dto->entity from a query with no .select I get the same error:

Error retreiving data. Property 'entityAspect' of object [object Object] is not a function

I am working in SPA using Breeze+Durandal my method to query is:

var getTratamentoByPacienteId = function (pacienteId, tratamentoObservable) {
        var query = entityQuery.from('Tratamentos')
            .where('pacienteId', '==', pacienteId)
            .expand("Cardapios.Refeicoes.TipoRefeicao, Cardapios.Refeicoes.ItensRefeicao.Alimento, Cardapios.Refeicoes.ItensRefeicao.UnidadeMedida");

        var result = manager.executeQuery(query)
            .then(querySucceeded)
            .fail(queryFailed);
        return result;

        function querySucceeded(data) {
            var list = partialMapper.mapDtosToEntities(manager, data.results, entityNames.tratamento, 'id');
            if (tratamentoObservable) {
                tratamentoObservable(list[0]);
            }
            log('Retrieved [Tratamento] from remote data source', data, true);
            return tratamentoObservable;
        }
    };

    function mapDtosToEntities(manager, dtos, entityName, keyName, extendWith) {
        return dtos.map(dtoToEntityMapper);

        function dtoToEntityMapper(dto) {
            var keyValue = dto[keyName];
            var entity = manager.getEntityByKey(entityName, keyValue);
            if (!entity) {
                // We don't have it, so create it as a partial
                extendWith = $.extend({}, extendWith || defaultExtension);
                extendWith[keyName] = keyValue;
                entity = manager.createEntity(entityName, extendWith);
            }
            mapToEntity(entity, dto);
            entity.entityAspect.setUnchanged();
            return entity;
        }

        function mapToEntity(entity, dto) {
            // entity is an object with observables
            // dto is from json
            for (var prop in dto) {
                if (dto.hasOwnProperty(prop)) {
                    entity[prop](dto[prop]); /*<- Error here*/
                }
            }
            return entity;
        }
    }

Upvotes: 0

Views: 961

Answers (2)

Jim Stott
Jim Stott

Reputation: 810

Ward's points are dead on, but to answer the very first part of your question

Every time I try to map a dto->entity from a query with no .select I get the same error:

What Breeze returns with .select statements are projections (simple js objects) - not entities. In your case, when you omit the select portion, a entity (with entityAspect property) is being returned.

In your existing case, you could remove properties in a couple of ways:

delete entity.entityAspect // remove directly

or via ko.mapping:

dto = ko.mapping.toJS(entity,{'ignore':['entityAspect']); // add any other props to ignore array

Slightly off topic, but one other thing to keep in mind, projections are not cached on the client (however, any entities they do contain would be).

Upvotes: 1

Ward
Ward

Reputation: 17863

I'm confused by your intention. The point of mapDtosToEntities is to map projection data (the data returned with a select) into entities. Your query returns entities already! Why are you mapping them?

Do not map entities as if they were dtos!

Below, if you care, is why the code bombs where it does.

Look at what mapToEntity is doing. It is coping every value of the supposed-Dto into a like-named property of a newly created entity. The presumption is that the dto only has raw JSON server data for selected properties.

But in your example, dto is actually a Tratamento entity whose data properties are Knockout functions, not raw data values. You're actually setting target entity properties to functions!

You're doing something like this:

var fn = dto.name;   // this is ko observable function, not a string!
tratamento.name(fn); // you just set the name to a function!

That is not what you want at all.

KO won't stop you because it really doesn't care what you assign. There is no JavaScript syntax problem either until ...

... the dto property loop (for (var prop in dto)...) finally gets around to the entityAspect property. Then you get the exception because you are effectively doing this:

tratamento.entityAspect(dto.entityAspect);

tratamento.entityAspect is a property, not a KO function.

That is what the error message is saying:

Property 'entityAspect' of object [object Object] is not a function

Upvotes: 1

Related Questions