Breeze EntityManager 没有删除导入的分离实体?

Breeze EntityManager not removing imported detached entites?

我正在使用 Wards excellent example 通过 breeze 实现多对多。 (我要在他的 post 中大放异彩,不能 link 从这里不知道为什么)

一切正常,更改始终正确保存到数据库。

我正在使用 2 个不同的 (BreezeJS) EntityManagers:一个用于编辑,一个作为我的 "master"。将编辑器 Em 保存到数据库后,它会将所有更改导入到主 Em 中,以使其保持同步。这对我的所有其他功能都非常有效。

但是,在保存多对多映射时,出于某种原因,任何已删除的映射都不会从主 Em 中删除。 (当我添加映射时,它们会立即正确显示在主 Em 中)。

我是否需要采取其他步骤让我的主控 Em 删除导入的分离实体?

(仅供参考,一切都正确保存到服务器,如果我进行硬页面刷新,我的所有实体都会正确显示)。

我在编辑器 Em 上删除实体的代码:myEntity.entityAspect.setDeleted();

下面的函数将从编辑器 Em 导出更改的实体:

  function exportToMasterAfterSavingSuccess(saveResult){
  if(saveResult.entities)
    masterEm.importEntities(manager.exportEntities(entities, false));
}

以及master em上对应的导入函数:

function importEntities(entities){
 var imported = manager.importEntities(entities,{ mergeStrategy: breeze.MergeStrategy.OverwriteChanges});
}

请使用最新发布的 breeze (1.5.3) 版本试试。那里修复了一个非常相似的错误。

需要说明的是,导出永远不能包含 'detached' 个实体(仅 'deleted' 个)。根据定义,分离的实体不再附加到 EntityManager,因此 EntityManager 不再了解它们。

我遇到了完全相同的问题。我没有做 many-to-many,但仍在单独的 entityManager 中做 edits/adds/deletes。

我可以确认导出确实包括分离的实体,并且在使用 MergeStrategy.OverwriteChanges 导入主实体管理器时,这些实体确实变得分离。

但是,新分离的实体仍与任何相关实体关联。

据我所知,重新连接和分离似乎使一切恢复同步:

var result = manager.importEntities(imports);
result.entities
    .filter(function (entity) { return entity.entityAspect.entityState.isDetached(); })
    .forEach(function (entity) { manager.attachEntity(entity); manager.detachEntity(entity); });

Breeze 1.5.3

Github 拉取请求问题: https://github.com/Breeze/breeze.js/issues/75

感谢您发现错误。人们不应该能够导出或导入一个分离的实体。将来,如果您尝试执行任一操作,Breeze 都会抛出异常。

现在我将讨论您的问题、您的目标以及我建议您做的事情。

保存删除的实体后更新主 EntityManager

据我了解,您维护了一个 masterEm,它只有实体的保存状态。您在单独的 editEm 中进行更改并保存。您将要更改的实体导入 editEm,进行更改,保存它们,然后(如果保存成功),从 editEm 导出保存的实体并将它们导入回 masterEm.这是一种常见的“沙盒编辑”模式。

当您删除 editEm 中的实体时出现问题。保存后,该实体在 editEm 中处于“分离”状态,但在 masterEm 中仍处于“未更改”状态。您如何传达实体已删除并将其从 masterEm 中删除的事实?

This dilemma exists independent of the "many-to-many" scenario that inspired your question.

我明白为什么您将现在分离的实体从 editEm 导入到 masterEm 的做法似乎有效。在 v.1.5.3 中这样做会导致 masterEm 中的相应实体更改为“分离”状态……这就是您想要的。如您所见,该错误是当导入的实体处于“分离”状态时,importEntities 方法无法正确处理导航属性的更新。您建议教 importEntities 在那种情况下“做正确的事”。

这里实际发生的是您发现了一个错误。您永远不应该能够导出“分离”实体,也不应该能够导入一个实体。当您尝试导出或导入“分离”实体时,Breeze 应该会抛出异常。

为什么要求 EntityManager 到 export/import“分离的”实体不是一个好主意的原因有很多。我将在另一天解释这些原因。

我们不会“解决”导入相关“分离”实体的问题,而是抛出一个错误。

这意味着您的部分解决方案将停止工作,使您显然比今天更糟。幸运的是,我为您提供了另一种方法。我已经编写了这个效用函数并对其进行了测试 in DocCode:

function updateMasterWithSaveResult(masterEm, sourceEm, saveResult) {
  var imports = [];
  var deletes = [];
  saveResult.entities.forEach(function(entity) {
    if (entity.entityAspect.entityState.isDetached()) {
      deletes.push(entity);
    } else {
      imports.push(entity);
    }
  });
  var exported = sourceEm.exportEntities(imports, {
    includeMetadata: false,
    asString: false // as JSON
  });
  masterEm.importEntities(exported);

  deletes.forEach(function(detached) {
    var entity = masterEm.getEntityByKey(detached.entityAspect.getKey());
    entity && entity.entityAspect.setDetached();
  });
}

更新文档

我几乎是逐字逐句地把这个添加到我们的 "Cool Breeze" documentation 中。