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

时间:2018-01-24 01:37:10

标签: breeze

我注意到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为“Added”的Title实体需要为所有链接的Person实体显式设置titleId属性为null。

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

要做到这一点似乎很笨拙。这种行为是故意的,出于某种原因逃脱了我吗?

2 个答案:

答案 0 :(得分:1)

在删除时,Breeze对

进行了重要区分
  • (案例a)仅存在于客户端上的实体(处于已添加状态的实体)和
  • (案例b)已保留在服务器上的实体。

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

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

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

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

答案 1 :(得分:1)

我认为这实际上应该修改Breeze以更智能地处理Added实体的删除。在此期间,以下可能代表一种解决方法(到目前为止我还没有机会尝试)。

首先,对于被删除的Added个实体,问题似乎是引用该实体的导航属性不会更新以删除这些引用。也许有可能欺骗Breeze来照顾它。

  1. 首先将要删除的已添加实体的状态设置为Unchanged
  2. 删除实体。由于实体的状态不再是Added,因此将删除转换为分离的逻辑将不适用。实体将其状态设置为Deleted,并且将更新引用它的导航属性,以便它们不再执行。
  3. 保留状态为Deleted的实体将是一个问题,因为会尝试删除实际上不存在的实体。将其状态设置为Detached以防止这种情况发生。
  4. 因此,不要只是删除,而是尝试将状态设置为Unchanged,然后删除并最终将状态设置为Detached