2

到目前为止,我有一个运行良好的单页应用程序,但我遇到了一个我无法弄清楚的问题。我正在使用轻风来填充要在表格中显示的项目列表。信息比我实际需要的要多得多,所以我正在对数据进行预测。我想在实体上添加一个计算出的淘汰赛。所以为了做到这一点,我像这样注册了实体构造函数......

metadataStore.registerEntityTypeCtor(entityNames.project, function () { this.isPartial = false; }, initializeProject);

initializeProject 函数使用项目中的一些值来确定计算的值应该是什么。例如,如果 Project.Type == "P" 那么 rowClass 应该 = "Red"。

我遇到的问题是 Project 的所有属性都是 null 除了 ProjNum 恰好是关键。我相信这个问题是因为我正在做投影,因为我已经为其他类型注册了其他初始化程序并且它们工作得很好。有没有办法使这项工作?

编辑:我想我会添加更多细节以进行澄清。所有属性的值都设置为敲除 observables,当我使用 Chrome 中的 javascript 调试器查询属性时,任何属性的 _latestValue 为空。唯一设置的属性是 ProjNum,它也是实体键。

EDIT2:这是进行投影的客户端代码

var getProjectPartials = function (projectObservable, username, forceRemote) {
    var p1 = new breeze.Predicate("ProjManager", "==", username);
    var p2 = new breeze.Predicate("ApprovalStatus", "!=", "X");
    var p3 = new breeze.Predicate("ApprovalStatus", "!=", "C");

    var select = 'ProjNum,Title,Type,ApprovalStatus,CurrentStep,StartDate,ProjTargetDate,CurTargDate';

    var isQaUser = cookies.getCookie("IsQaUser");

    if (isQaUser == "True") {
        p1 = new breeze.Predicate("QAManager", "==", username);
        select = select + ',QAManager';
    } else {
        select = select + ',ProjManager';
    }

    var query = entityQuery
        .from('Projects')
        .where(p1.and(p2).and(p3))
        .select(select);

    if (!forceRemote) {
        var p = getLocal(query);
        if (p.length > 1) {
            projectObservable(p);
            return Q.resolve();
        }
    }

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

    function querySucceeded(data) {
        var list = partialMapper.mapDtosToEntities(
            manager,
            data.results,
            model.entityNames.project,
            'ProjNum'
        );
        if (projectObservable) {
            projectObservable(list);
        }
        log('Retrieved projects using breeze', data, true);
    }
};

以及 partialMapper.mapDtosToEntities 函数的代码。

var defaultExtension = { isPartial: true };

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) {
            extendWith = $.extend({}, extendWith || defaultExtension);
            extendWith[keyName] = keyValue;
            entity = manager.createEntity(entityName, extendWith);
        }
        mapToEntity(entity, dto);
        entity.entityAspect.setUnchanged();
        return entity;
    }

    function mapToEntity(entity, dto) {
        for (var prop in dto) {
            if (dto.hasOwnProperty(prop)) {
                entity[prop](dto[prop]);
            }
        }
        return entity;
    }
}

EDIT3:看起来这是我的错误。当我仔细查看 initializeProject 时发现了错误。下面是我修复它之前的功能。

function initializeProject(project) {
    project.rowClass = ko.computed(function() {
        if (project.Type == "R") {
            return "project-list-item info";
        } else if (project.Type == "P") {
            return "project-list-item error";
        }
        return "project-list-item";
    });
}

问题出在 project.Type 我应该使用 project.Type() 因为它是可观察的。自从开始这个项目以来,我犯了太多次是一个愚蠢的错误。

EDIT4:在 initializeProject 内部,一些部分正在工作,而另一些则没有。当我尝试访问 project.ProjTargetDate() 时,我得到 null,与 project.StartDate() 相同。由于 Null 值,当我使用这些日期来确定项目何时延迟时,我会从 moment 库中抛出一个错误。我尝试从客户端查询和对部分实体映射器的调用中删除选择,当我这样做时一切正常。

4

1 回答 1

2

你似乎越来越近了。我认为在你的initializeProject方法中添加更多的保护子句会有所帮助,并且在使用 Knockout 时,人们一直在与括号问题作斗争。

顺便说一句,我强烈推荐用于 Chrome 的Knockout Context Debugger插件来诊断绑定问题。

尝试 toType()

您正在非常努力地处理 DTO 映射,并遵循 John 课程中的代码。从那时起,就有了一种将投影数据导入实体的新方法:添加toType(...)到查询的末尾,如下所示:

var查询=实体查询
        .from('项目')
        .where(p1.and(p2).and(p3))
        .select(选择)
        .toType('项目') ; // 转换为项目

它不会解决所有问题,但您可以取消 dto 映射。

考虑服务器上的 DTO

我应该先指出这一点。如果您总是将这些数据缩减到合适的大小,为什么不定义面向客户的模型以适合您的客户。在通过网络发送数据之前,创建正确形状的 DTO 类并将其投影到服务器上。

您还可以构建元数据以匹配这些 DTO,以便Project在客户端上完全具有它应该具有的属性......仅此而已。

我现在正在写这个。一周左右应该有一个页面。

于 2013-05-08T17:23:38.920 回答