Breeze.js - 删除新的 (EntityState = "Added") 实体时未清除外键

Breeze.js - foreign keys not cleared when deleting a new (EntityState = "Added") entity

我注意到在 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 属性 和标题导航 属性为空。

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

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

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

不得不这样做似乎很笨拙。这种行为是故意的,出于某种让我逃避的原因吗?

关于删除,Breeze 对

进行了重要区分
  • (案例 a) 实体仅存在于客户端(那些处于已添加状态),并且
  • (case b) 已持久保存在服务器上的实体。

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

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

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

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

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

首先,对于 Added 个被删除的实体,问题似乎是引用该实体的导航属性没有得到更新以删除这些引用。或许可以诱骗 Breeze 来照看它。

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

因此,与其直接删除,不如尝试将状态设置为 Unchanged,然后删除,最后将状态设置为 Detached