【发布时间】:2015-02-20 15:44:09
【问题描述】:
我最近需要实现一个 UI 来管理多对多关系。 Ward Bell 好心地提供了this plunker,展示了如何在 Angular 和 Breeze 中使用 1-m-1。
我的应用程序的设计主要基于 John Papa 最近的 Pluralsight 课程(尤其是数据上下文和本地存储)。
在我的应用中,BusUnit = Hero 和 Dimension = Power(参考 Ward 的示例。
当我强制应用程序从服务器获取数据时,一切似乎都运行良好,因为我对业务单位维度的更新反映正确。我现在面临的问题是当我离开页面并再次返回时(从本地存储中获取数据)。在这种情况下:
- 如果我之前向业务部门添加了新维度,一切正常,但是
- 如果我之前将某个业务单位的维度标记为删除和保存,则相关业务单位的维度仍会显示。
这是最初获取业务单位及其维度的控制器代码:
function getdboardStructure() {
var busUnitsPromise = datacontextSvc.busUnits.getByDboardConfigId(vm.dboardConfig.id);
var dimensionsPromise = datacontextSvc.dimensions.getByDboardConfigId(vm.dboardConfig.id);
$q.all([busUnitsPromise, dimensionsPromise])
.then(function (values) {
vm.busUnits = values[0];
vm.dims = values[1];
createBusUnitVms();
//vm.currentBusUnitVm = vm.busUnitVms[0]; // not required as using accordion instead of drop-down
vm.hasChanges = false;
});
}
这是我的控制器中准备保存的代码:
function applyBusUnitDimensionSelections(busUnitVm) {
var busUnit = busUnitVm.busUnit;
var mapVms = busUnitVm.dimensionMapVms;
var dimensionHash = createBusUnitDimensionHash(busUnit);
mapVms.forEach(function (mapVm) {
var map = dimensionHash[mapVm.dimension.id];
if (mapVm.selected) {
if (!map) {
datacontextSvc.busUnits.addBusUnitDimension(busUnit, mapVm.dimension)
.then(function () {
});
}
} else {
if (map) {
datacontextSvc.markDeleted(map);
}
}
});
}
这是我的控制器中执行保存的代码:
function save() {
if (!canSave()) {
return $q.when(null);
}
vm.isSaving = true;
vm.busUnitVms.forEach(applyBusUnitDimensionSelections);
return datacontextSvc.save().then(function (saveResult) {
vm.isSaving = false;
trapSavedDboardConfigId(saveResult); // not relevant to use case
}, function (error) {
vm.isSaving = false;
});
}
这是我的存储库中添加新 busUnitDimension 实体的代码:
function addBusUnitDimension(busUnit, dimension) {
var newBusUnitDimension = this.em.createEntity(busUnitDimension);
newBusUnitDimension.busUnitId = busUnit.id;
newBusUnitDimension.dimensionId = dimension.id;
return this.$q.when(newBusUnitDimension);
}
这是我用于标记已删除项目的数据上下文代码:
function markDeleted(entity) {
return entity.entityAspect.setDeleted();
}
最后这是获取业务单位及其连接表实体的存储库代码:
function getByDboardConfigId(dboardConfigId, forceRefresh) {
var self = this;
var predicate = pred.create('dboardConfigId', '==', dboardConfigId);
var busUnits;
if (self.zStorage.areItemsLoaded('busUnits') && !forceRefresh) {
busUnits = self._getAllLocal(entityName, orderBy, predicate);
return self.$q.when(busUnits);
}
return eq.from('BusUnits')
.expand('BusUnitDimensions')
.where(predicate)
.orderBy(orderBy)
.using(self.em).execute()
.to$q(succeeded, self._failed);
function succeeded(data) {
busUnits = data.results;
self.zStorage.areItemsLoaded('busUnits', true);
self.zStorage.save();
//self.logSuccess('Retrieved ' + busUnits.length + ' business units from server', busUnits.length, true);
return busUnits;
}
}
我与 John 的课程示例的不同之处在于,我在用于从服务器获取业务单位的函数中使用了 expand,我的假设是,这与微风每次都进入服务器这一事实有关我改为刷新页面(不清除缓存),这也与我在导航离开然后返回页面时收到的错误有关。
任何人都可以提供和建议吗?
【问题讨论】:
-
我不太明白你在问什么,但考虑到你在这个主题上提出的大量问题以及压倒性的支持,我建议你从保持微风的公司那里获得有偿支持。您已经冒险进入了像我这样的普通人难以遵循的高度自定义场景的领域。
-
我同意你的观点,但我的观点是这个话题会引起许多 SO 用户的兴趣,并且在此处发布问题将为有类似要求的人提供价值。尽管需求可能是一个共同点,但这些问题都与满足需求的不同方面有关。
-
但我仍然不知道您在谈论什么共同点、要求或其他任何内容。
-
我真的无法通过所有这些代码。但我的直觉与你的相似……缓存中的数据不再反映服务器的状态。如果您允许删除,事情就会快速发展。您需要防范这种故障,并准备通过清除不再准确的(选定)实体的缓存(例如删除的“busUnits”及其依赖项)来恢复。一个粗略但安全的方法是在服务器抛出保存异常时放弃,向用户道歉,清除所有易失实体的缓存,然后重新开始。