我有一个单页应用程序到目前为止工作得很好,但我遇到了一个我无法弄清楚的问题。我正在使用breeze来填充要在表格中显示的项目列表。有比我实际需要更多的信息,所以我正在对数据进行投影。我想在实体上添加一个计算结果。所以要完成这个我注册和实体构造函数就像这样......
metadataStore.registerEntityTypeCtor(entityNames.project, function () { this.isPartial = false; }, initializeProject);
initializeProject函数使用项目中的一些值来确定计算值应该是什么。例如,如果Project.Type ==“P”,则rowClass应为=“Red”。
我遇到的问题是Project的所有属性都是null,除了恰好是关键的ProjNum。我相信这个问题是因为我正在进行投影,因为我已经为其他类型注册了其他初始化器,它们工作得很好。有没有办法使这项工作?
编辑:我想我只想添加一些细节以便澄清。所有属性的值都设置为knockout observables,当我使用Chrome中的javascript调试器查询属性时,任何属性的_latestValue都为null。设置的唯一属性是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值,我从当前库中得到一个错误,因为我正在使用这些日期来确定项目何时迟到。我尝试从客户端查询和对部分实体映射器的调用中删除select,当我这样做时,一切正常。
答案 0 :(得分:2)
你似乎越来越近了。我认为你initializeProject
方法中的一些保护条款会有所帮助,在与Knockout合作时,人们总是在与括号问题作斗争。
顺便说一句,我强烈推荐Chrome的Knockout Context Debugger插件来诊断绑定问题。
你正在努力完成你的DTO映射,并跟随他的课程中的John代码。从那时起,有一种将投影数据导入实体的新方法:将toType(...)
添加到查询的末尾,如下所示:
var query = entityQuery .from('Projects') .where(p1.and(p2).and(p3)) .select(select) .toType('Project'); // cast to Project
它无法解决所有问题,但您可以取消dto映射。
我应该首先指出这一点。如果您始终将此数据缩小到适当大小,为什么不定义面向客户端的模型以适合您的客户。在通过网络发送数据之前,创建正确形状的DTO类并在服务器上投影到它们中。
您还可以构建元数据以匹配这些DTO,以便客户端上的Project
具有应该具有的属性......而不再有。
我现在正在写这个。在一周左右的时间内应该有一个页面。