【问题标题】:Breeze.js - foreign keys not cleared when deleting a new (EntityState = "Added") entityBreeze.js - 删除新 (EntityState = "Added") 实体时未清除外键
【发布时间】:2018-02-08 15:11:27
【问题描述】:

我注意到 Breeze.js 在删除尚未持久化的实体 (EntityState = "Added") 和持久化实体之间的任何引用(外键)之间存在令人讨厌的差异。

这可能是与为新实体生成临时密钥有关的问题。在这种情况下,我们为临时键(id)生成负数,并在它们被持久化时替换为实际键。

这将通过一个具体的例子更容易地解释。假设我们有一个名为 Person 的实体,它包含对 Title 实体(“Mr”、“Mrs”等)的引用:

export class Person extends EntityBase {
    id: number;
    firstName: string;
    lastName: string;
    titleId: number;
    title: Title;
    ...
}

export class Title extends EntityBase {
    id: number;
    name: string;
    ...
}

现在,如果我们在当前上下文中有一个持久的 Title 实体并对其调用 .setDeleted() ,则适用的 Person 实体上的 titleId 属性和标题导航属性都设置为 null。

但是,如果 Title 实体的 EntityState 为“Added”,则只有所有链接的 Person 实体上的标题导航属性设置为 null。 titleId 属性保留其值,导致保存时出错(违反外键约束)。

这意味着删除 EntityState 为“已添加”的 Title 实体需要将所有链接的 Person 实体的 titleId 属性显式设置为 null。

可能值得注意的是,底层数据库中的 TitleID 列可以为空。如果不是,我们当然必须将 titleId 属性设置为合适的值。

必须这样做似乎很笨拙。这种行为是故意的吗?出于某种我无法理解的原因?

【问题讨论】:

    标签: breeze


    【解决方案1】:

    在删除方面,Breeze 做出了重要的区分

    • (case a) 仅存在于客户端的实体(处于已添加状态的实体),以及
    • (case b) 已在服务器上持久化的实体。

    对于已经持久化的实体(案例 b),Breeze 必须跟踪该删除的实体, 并将删除发送到服务器。必须更新服务器上的任何外键 删除对已删除实体的引用,因此轻而易举会相应地更新相关的客户端实体 并将这些更改也发送到服务器。

    对于一个新创建的实体(案例a),服务器对此一无所知。几时 在客户端上“删除”,Breeze 实际上并没有设置它Deleted,因为它没有 需要向服务器发送删除。相反,它将它设置为Detached。

    当一个实体被设置为Detached时,它的导航属性被设置为null,并且它 从 EntityManager 的缓存中删除。它的外键属性没有改变, 但是,因此,如果您分离实体并重新附加它,导航属性将 重新连接。无论实体是 Added 还是之前的任何其他状态都是如此 它变成了Detached。

    有关实体状态的更多信息,请参阅Breeze documentation

    【讨论】:

    • 在 EntityState 为 Additional 的实体上调用 setDetached() 时这是有道理的,但是当您在实体上调用 setDeleted() 时,它是非常明确的 - 您说您希望将其删除。是的,在幕后,Breeze 只是将它分离,但留下引用它的外键对我来说似乎很草率。在什么可能的情况下留下这些键(现在引用一个永远不会存在的实体)是有用的?
    • 我同意@ToboldHornblower。仅将添加实体的删除视为分离会使事情过于简单化。如果我要删除,那是因为我不希望该实体出现在数据库中。如果实体的记录不在数据库中,那么引用它的外键总是会出现问题。在删除期间应清理它们所基于的导航属性。理想情况下,微风会照顾好它。取而代之的是,有什么方法可以手动处理吗?以某种方式挂钩用于删除的逻辑?
    【解决方案2】:

    我认为这实际上是应该修改 Breeze 以更智能地处理 Added 实体的删除的情况。但与此同时,以下可能是一种解决方法(目前我还没有机会尝试)。

    首先对于被删除的Added 实体,问题似乎是引用实体的导航属性没有更新以删除这些引用。有可能诱使 Breeze 照看这个。

    1. 首先将要删除的添加实体的状态设置为Unchanged。
    2. 删除实体。因为实体的状态不再是Added,所以将Delete 转换为Detach 的逻辑将不适用。该实体将其状态设置为Deleted,并且引用它的导航属性将被更新,以便它们不再这样做。
    3. 让实体状态为Deleted 将是一个问题,因为会尝试删除实际不存在的实体。将其状态设置为 Detached 以防止这种情况发生。

    所以不要只是删除,而是尝试将状态设置为Unchanged,然后删除,最后将状态设置为Detached。

    【讨论】:

      猜你喜欢
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多