gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 08:59:03 27 4
gpt4 key购买 nike

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

我的问题:难道不应该轻而易举地意识到我们正在通过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);
    });

    这种方法至少存在四个问题:
  • 每个查询的实体都是一个幽灵。如果您的用户界面显示任何查询的实体,它将显示幻影。即使在服务器上根本没有触摸实体(99%的时间),也是如此。太糟糕了。您必须重新粉刷整个页面。

    您也许可以做到这一点。但是从很多方面来说,这种技术几乎和第一种技术一样不切实际。这意味着在任何地方进行任何查询之后,ever view都可能处于无效状态。
  • 分离实体具有副作用。依赖于您分离的对象的所有其他实体都会立即(a)更改并且(b)成为孤立对象。如下面的“孤立”部分所述,无法从中轻松恢复。
  • 此技术清除了您正在查询的实体之间的所有未决更改。我们很快就会看到如何处理。
  • 如果查询由于某种原因失败(连接丢失?),则无任何显示。除非您记得删除的内容,否则在查询失败的情况下可以将这些实体放回缓存中。

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

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

    我将要描述的方法通常称为“标记和扫描”。
  • 在本地运行查询,并按照上述方法计算实体的inCache列表。这次,请而不是从缓存中删除那些实体。查询成功后,我们将删除保留在此列表中的实体……但不是现在。
  • 如果查询的MergeOption为“PreserveChanges”(默认情况下),请从inCache列表(而不是从管理器的缓存中!)中删除所有有待更改的实体。我们这样做是因为无论服务器上实体的状态如何,此类实体都必须保留在缓存中。这就是“PreserveChanges”的意思。

    我们可以在第二种方法中做到这一点,以避免删除未保存更改的实体。
  • 订阅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);
    }
    }
    }
  • 如果查询失败,请忘记所有此
  • 如果查询成功
  • 退订:manager.entityChanged.unsubscribe(handlerId);
  • 订阅孤儿检测处理程序
    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
    }
    }
  • 分离保留在inCache列表中的每个实体。
    inCache.slice().forEach(function(e) {
    manager.detachEntity(e);
    });
  • 取消订阅孤儿检测处理程序

  • 孤儿探测器?

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

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

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

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

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

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

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

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

    然后,当您查询最新产品时,情况就不那么糟了,其中一个产品引用了缓存中没有的新 Color(“香蕉”)。

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

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

    那鬼呢?

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

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

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

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

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

    服务器通知呢?

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

    关于breeze - Breeze :子实体已被其他人删除后,在重新加载父实体后它们仍然出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22182101/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com