【发布时间】:2012-12-11 20:18:21
【问题描述】:
我有两张表,一张表 A 是父表,另一张表 B 是子表(1:N 关系)。
如果我想在删除表A中的父时删除表B中的子记录,如果我不在数据库中使用级联删除,我会按照以下方式进行:
- 用户 A 在她的上下文中加载父记录,然后在上下文中加载所有子记录,将所有记录标记为已删除。
- 其他用户添加新的孩子。
- 用户 A 保存更改。出现引用完整性错误,因为第二个用户添加的寄存器不在她的上下文中。
在这种情况下,第一个用户可以在引发异常时再次尝试加载所有子级,但第三个用户可以添加一个新的子级并遇到同样的问题。理论上,这可能一直发生,并且第一个用户不会删除父级。
出于这个原因,我正在考虑使用事务来完成这项工作。
- 第一个用户开始交易。
- 第一个用户标记为已删除父级并保存更改。父级在数据库中被阻止。
- 第一个用户加载所有孩子,标记为已删除。
- 第一位用户保存更改。
在这种情况下,我有一个疑问,当父注册被第一个用户阻止时,这个父的ID可以被其他用户用作子记录的外键吗?还是数据库不允许使用ID,因为理论上是一条已删除的记录?
如果数据库不允许使用该ID,第二个用户在尝试添加新的子节点时会出现异常,以保证引用完整性,因为父节点不存在。所以问题就解决了。不需要做其他任何事情。
但是,如果数据库允许使用被阻止父级的 ID,我需要做两件事:
在删除父对象的方法中:
- 加载父级,将其标记为已删除并保存更改。这会阻止寄存器。
- 加载子项,将其标记为已删除并保存更改。
- 接受交易。
在添加孩子的方法中
- 加载父级。如果被阻塞,该方法等待直到寄存器空闲。
- 添加新的孩子。
- 接受更改。
确实不需要在上下文中加载父级来删除子级,这将是对数据库的额外查询。
如果父级不存在,则获取异常并且不需要执行任何其他操作,用户现在尝试添加新注册是因为父级已被删除。
如果父级存在,则可以添加子级。
所以我有两个问题。
使用事务删除父记录以确保删除所有子记录是个好主意吗?
如果事务是一个不错的选择,当父节点被阻塞时,数据库不允许使用父 ID 添加新记录或者我需要在方法中加载父节点的解决方案删除孩子?
【问题讨论】:
-
您无法将父级标记为已删除并保存更改。 EF 将尝试删除记录,违反 FK 约束。还是通过在数据库字段中设置标志来标记为已删除?
-
如果我没记错的话,如果我在一个事务中,当将父标记为已删除并进行第一次保存更改时,没有问题,因为我仍然不接受该事务。但这是理论上的,我没有做过测试。
标签: c# entity-framework transactions cascading-deletes