我有两个表,一个表 A 是父表,另一个表 B 是子表(1:N 关系)。
如果我想在删除表A中的父时删除表B中的子记录,如果我不在数据库中使用级联删除,我会按照以下方式进行:
- 用户 A 在她的上下文中加载父记录,然后在上下文中加载所有子记录,将所有记录标记为已删除。
- 其他用户添加一个新的孩子。
- 用户 A 保存更改。由于第二个用户添加的寄存器不在她的上下文中,因此出现引用完整性错误。
在这种情况下,第一个用户可以在引发异常时再次尝试加载所有子级,但第三个用户可以添加一个新的子级并遇到同样的问题。理论上,这可能一直发生,第一个用户不会删除父级。
出于这个原因,我正在考虑使用事务来完成这项工作。
- 第一个用户开始交易。
- 第一个用户标记为已删除父级并保存更改。父级在数据库中被阻止。
- 第一个用户加载所有孩子,标记为已删除。
- 第一个用户保存更改。
在这种情况下,我有一个疑问,当父注册被第一个用户阻止时,这个父的ID可以被其他用户用作子记录的外键吗?还是数据库不允许使用ID,因为理论上是一条已删除的记录?
如果数据库不允许使用该 ID,则第二个用户在尝试添加新子代时会出现异常,以确保引用完整性,因为父代不存在。所以问题就解决了。不需要做任何其他事情。
但是,如果数据库允许使用被阻止父级的 ID,我需要做两件事:
在删除父级的方法中:
- 加载父级,将其标记为已删除并保存更改。这会阻止寄存器。
- 加载孩子,将它们标记为已删除并保存更改。
- 接受交易。
在添加孩子的方法中
- 加载父级。如果被阻塞,则该方法等待直到寄存器空闲。
- 添加新的孩子。
- 接受更改。
确实不需要在上下文中加载父级来删除子级,这将是对数据库的额外查询。
如果父级不存在,则获取异常并且不需要执行任何其他操作,用户现在尝试添加新寄存器是因为父级已被删除。
如果父级存在,则可以添加子级。
所以我有两个问题。
使用事务删除父记录以确保删除所有子记录是个好主意吗?
如果事务是一个不错的选择,当父级被阻塞时,数据库不允许使用父级ID添加新记录或者我需要在删除子级的方法中加载父级的解决方案?