微风:子实体已被其他人删除后,在重新加载父实体后它们仍然出现

德申斯

我们有一个轻而易举的客户解决方案,其中向父实体显示其子列表。我们对某些子实体进行硬删除。现在,当用户是执行删除操作的用户时,没有问题,但是当其他用户执行操作时,似乎没有办法使已经加载到缓存中的子项失效。我们对父级执行一个新查询并扩展到子级,但是即使数据库未返回它们,微风也会附加已经听到的所有其他子级。

我的问题:难道不应该轻而易举地意识到我们正在通过expand进行加载,从而在从db重新加载结果之前从缓存中完全删除所有子级吗?如果不是这种情况,我们还能怎么做呢?

谢谢

病房

是的,这确实是一个好点。

删除只是每项数据管理工作的一个可怕的麻烦无论是否使用Breeze,这都是事实。它只会引起上下上下的心痛。这就是为什么我建议软删除而不是硬删除的原因。

但是您不在乎我的想法...所以我会继续。

让我直接说一下。没有简单的方法可以正确地实现缓存清除方案我将描述我们将如何做到(我敢肯定有些细节被忽略了),您会明白为什么这样做很困难,在不正常的情况下却毫无结果。

当然,最有效,最强力的方法是在查询之前清空缓存。如果这样做的话,您可能也没有缓存,但是我想我会提一下。

“独立”实体问题

在继续之前,请记住我刚刚提到的技术,并且如果您的UI(或其他任何东西)持有对您要删除的实体的引用,那么实际上所有可能的解决方案都是无用的。

哦,您会从缓存中删除它们的。但是,无论现在持有对它们的引用,将继续对处于“已分离”状态的实体对象(即虚影)进行引用。确保没有发生是您的责任;如果Breeze知道,它就不会知道,也不会做任何事情。

第二次尝试

第二种不太平淡的方法(由杰伊建议)是

  • 首先将查询应用于缓存
  • 遍历结果,每一遍
    • 沿“展开”路径分离每个子实体。
    • 分离该顶级实体

现在,查询成功后,您便拥有了清除缓存的明确道路。

这是一个简单的代码示例,因为它与TodoLists及其TodoItems的查询有关:

var query = breeze.EntityQuery.from('TodoLists').expand('TodoItems');

var inCache = manager.executeQueryLocally(query);
inCache.slice().forEach(function(e) {
    inCache = inCache.concat(e.TodoItems);
});

inCache.slice().forEach(function(e) {
    manager.detachEntity(e);
});

这种方法至少存在四个问题:

  1. 每个被查询的实体都是一个幽灵。如果您的UI正在显示任何查询的实体,它将显示幻影。即使在服务器上根本没有触摸实体(99%的时间),也是如此。太糟糕了。您必须重新粉刷整个页面。

    您也许可以做到这一点。但是从很多方面来说,这种技术几乎和第一种技术一样不切实际。这意味着在任何地方进行任何查询后,ever view都可能处于无效状态。

  2. 分离实体有副作用。依赖于您分离的对象的所有其他实体都会立即(a)更改并且(b)成为孤立对象。如下面的“孤立”部分所述,无法从中轻松恢复。

  3. 此技术清除了您正在查询的实体之间的所有未决更改。我们很快就会看到如何处理。

  4. 如果查询由于某种原因失败(连接丢失?),则无任何显示。除非您记得删除的内容,否则在查询失败的情况下可以将这些实体放回缓存中。

为什么要提及一种可能具有有限实用价值的技术?因为这是方法3可行的一步

尝试#3-这实际上可能有效

我将要描述的方法通常称为“标记和扫描”。

  1. 在本地运行查询并按照上述说明计算inCache实体列表。这个时候,就不会从缓存中删除这些实体。查询成功后,我们将删除保留在该列表中的实体……但不是现在。

  2. 如果查询的MergeOption是“ PreserveChanges”(默认情况下为“ PreserveChanges”),请从inCache列表(而不是从管理器的缓存中)删除列表中所有有待更改的实体我们这样做是因为无论服务器上实体的状态如何,此类实体都必须保留在缓存中。这就是“ PreserveChanges”的意思。

    我们可以在第二种方法中做到这一点,以避免删除具有未保存更改的实体。

  3. 订阅EntityManager.entityChanged活动。在您的处理程序中,从inCache列表中删除“已更改的实体”,因为该实体由查询返回并合并到缓存中这一事实表明您该实体仍然存在于服务器上。这是一些代码:

    var handlerId = manager.entityChanged.subscribe(trackQueryResults);
    
    function trackQueryResults(changeArgs) {
        var action = changeArgs.entityAction;
        if (action === breeze.EntityAction.AttachOnQuery ||
            action === breeze.EntityAction.MergeOnQuery) {
            var ix = inCache.indexOf(changeArgs.entity);
            if (ix > -1) {
                inCache.splice(ix, 1);
            }
        }
    }
    
  4. 如果查询失败,请忘记所有这些

  5. 如果查询成功

    1. 退订: manager.entityChanged.unsubscribe(handlerId);

    2. 订阅孤儿检测处理程序

      var handlerId = manager.entityChanged.subscribe(orphanDetector);
      
      function orphanDetector(changeArgs) {
          var action = changeArgs.entityAction;
          if (action === breeze.EntityAction.PropertyChange) {
             var orphan = changeArgs.entity;
             // do something about this orphan
          }
       }
      
    3. 分离inCache列表中剩余的每个实体

      inCache.slice().forEach(function(e) {
          manager.detachEntity(e);
      });
      
    4. 取消订阅孤立检测程序

孤儿探测器?

分离实体可能会产生副作用。假设我们有Products,每个产品都有一个Color其他一些用户讨厌“红色”。她删除了一些红色产品,并将其余的更改为“蓝色”。然后,她删除了“红色” Color

您对此一无所知,并且天真地重新查询Colors“红色”颜色消失了,您的清理过程将其与缓存分离。立即Product修改每个缓存。Breeze不知道新产品Color应该是什么,因此它将Product.colorId每个以前的“红色”产品的FK设置为零。

没有Colorid = 0,因此所有这些产品都处于无效状态(违反了参照完整性约束)。他们没有Color父母。他们是孤儿。

两个问题:您怎么知道这件事发生在您身上,您怎么办?

当您分离“红色”颜色时,检测微风会更新受影响的产品。

您可以听取PropertyChanged在分离过程中引发事件。这就是我在代码示例中所做的。从理论上(我认为是“实际上”),PropertyChanged在分离过程中唯一可以触发事件的是“孤立”副作用。

你是做什么?

  • 让孤儿处于无效的修改状态?
  • 恢复colorId为删除的“红色”颜色同样无效的前者
  • 刷新孤儿以获取其新的颜色状态(或发现它已被删除)?

没有好的答案。您可以使用前两个选项来选择邪恶。我可能会选择第二个,因为它似乎破坏性最小。这将使产品处于“不变”状态,表示不存在Color

当您查询最新产品时,情况并不差很多,其中一个产品是指Color您没有缓存的新产品(“香蕉”)。

从技术上讲,“刷新”选项似乎是最好的。这很笨拙。它可以轻松地级联成一长串异步查询,这可能需要很长时间才能完成。

完美的解决方案使我们无法掌握。

那鬼呢?

哦,对了。您的UI可能仍会显示您分离的(较少)实体,因为您认为它们已在服务器上删除。您必须从用户界面中删除这些“鬼”。

我确定您可以弄清楚如何删除它们。但是您必须首先了解它们。

您可以遍历所显示的每个实体,并查看其是否处于“已分离”状态。UCK!

更好的是,我认为如果清理机制发布了一个(custom?)事件,其中包含您在清理过程中分离的实体的列表,而该列表为inCache然后,您的订户知道哪些实体必须从显示中删除...并可以做出适当的响应。

ew!我确定我已经忘记了一些东西。但是现在您了解了问题的严重性。

服务器通知呢?

那确实有可能。如果您可以安排服务器在删除任何实体时通知客户端,则可以在您的UI中共享该信息,并且可以采取措施来删除死角。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

重新附加父实体时删除子实体

来自分类Dev

用户/组/其他人 rwx 权限后最后的“+”是什么意思

来自分类Dev

实体删除后仍然可以找到

来自分类Dev

其他人的传奇

来自分类Dev

在“ top”命令并按“ c”键后如何拒绝其他人查看我的跑步详细信息

来自分类Dev

在完成机器学习项目后,我如何将其保存以供其他人查看

来自分类Dev

实体框架-有效删除所有子实体而无需加载它们

来自分类Dev

实体框架-有效删除所有子实体而不加载它们

来自分类Dev

如何按用户存储数据并防止其他人看到它们

来自分类Dev

Git从其他人删除的远程中删除最后的提交

来自分类Dev

git删除文件而团队中其他人没有删除它

来自分类Dev

在获取父实体EFCore时加载子实体

来自分类Dev

为什么不从其他人的本地存储库中删除目录?

来自分类Dev

删除补丁集中的其他人标志需要哪些权限?

来自分类Dev

如何在我的主页上删除其他人的仓库?

来自分类Dev

如何让discord.js让某人添加和删除其他人的角色

来自分类Dev

删除-秘密密钥不可用(其他人的密钥)

来自分类Dev

如何在我的网站上删除其他人的Facebook评论?

来自分类Dev

将我自己删除为其他人的项目的编辑

来自分类Dev

如何从其他人拥有的文件夹中删除文件

来自分类Dev

在Windows 10上完全控制我并禁止其他人删除

来自分类Dev

如何从合并请求中的其他人删除提交

来自分类Dev

当它与其他人没有链接时,mysql删除元素

来自分类Dev

JQuery 使用其他人拥有的类删除特定元素

来自分类Dev

Jquery添加点击事件并将其删除给其他人

来自分类Dev

如何从字典中删除项目并更改其他人的键 F#

来自分类Dev

在选择时删除课程并将课程添加到其他人

来自分类Dev

插入子实体后,GreenDAO不会更新实体的子树

来自分类Dev

防止其他人使用我的dll

Related 相关文章

  1. 1

    重新附加父实体时删除子实体

  2. 2

    用户/组/其他人 rwx 权限后最后的“+”是什么意思

  3. 3

    实体删除后仍然可以找到

  4. 4

    其他人的传奇

  5. 5

    在“ top”命令并按“ c”键后如何拒绝其他人查看我的跑步详细信息

  6. 6

    在完成机器学习项目后,我如何将其保存以供其他人查看

  7. 7

    实体框架-有效删除所有子实体而无需加载它们

  8. 8

    实体框架-有效删除所有子实体而不加载它们

  9. 9

    如何按用户存储数据并防止其他人看到它们

  10. 10

    Git从其他人删除的远程中删除最后的提交

  11. 11

    git删除文件而团队中其他人没有删除它

  12. 12

    在获取父实体EFCore时加载子实体

  13. 13

    为什么不从其他人的本地存储库中删除目录?

  14. 14

    删除补丁集中的其他人标志需要哪些权限?

  15. 15

    如何在我的主页上删除其他人的仓库?

  16. 16

    如何让discord.js让某人添加和删除其他人的角色

  17. 17

    删除-秘密密钥不可用(其他人的密钥)

  18. 18

    如何在我的网站上删除其他人的Facebook评论?

  19. 19

    将我自己删除为其他人的项目的编辑

  20. 20

    如何从其他人拥有的文件夹中删除文件

  21. 21

    在Windows 10上完全控制我并禁止其他人删除

  22. 22

    如何从合并请求中的其他人删除提交

  23. 23

    当它与其他人没有链接时,mysql删除元素

  24. 24

    JQuery 使用其他人拥有的类删除特定元素

  25. 25

    Jquery添加点击事件并将其删除给其他人

  26. 26

    如何从字典中删除项目并更改其他人的键 F#

  27. 27

    在选择时删除课程并将课程添加到其他人

  28. 28

    插入子实体后,GreenDAO不会更新实体的子树

  29. 29

    防止其他人使用我的dll

热门标签

归档