【问题标题】:Transaction is a good option to delete children records?事务是删除子记录的好选择吗?
【发布时间】:2012-12-11 20:18:21
【问题描述】:

我有两张表,一张表 A 是父表,另一张表 B 是子表(1:N 关系)。

如果我想在删除表A中的父时删除表B中的子记录,如果我不在数据库中使用级联删除,我会按照以下方式进行:

  1. 用户 A 在她的上下文中加载父记录,然后在上下文中加载所有子记录,将所有记录标记为已删除。
  2. 其他用户添加新的孩子。
  3. 用户 A 保存更改。出现引用完整性错误,因为第二个用户添加的寄存器不在她的上下文中。

在这种情况下,第一个用户可以在引发异常时再次尝试加载所有子级,但第三个用户可以添加一个新的子级并遇到同样的问题。理论上,这可能一直发生,并且第一个用户不会删除父级。

出于这个原因,我正在考虑使用事务来完成这项工作。

  1. 第一个用户开始交易。
  2. 第一个用户标记为已删除父级并保存更改。父级在数据库中被阻止。
  3. 第一个用户加载所有孩子,标记为已删除。
  4. 第一位用户保存更改。

在这种情况下,我有一个疑问,当父注册被第一个用户阻止时,这个父的ID可以被其他用户用作子记录的外键吗?还是数据库不允许使用ID,因为理论上是一条已删除的记录?

如果数据库不允许使用该ID,第二个用户在尝试添加新的子节点时会出现异常,以保证引用完整性,因为父节点不存在。所以问题就解决了。不需要做其他任何事情。

但是,如果数据库允许使用被阻止父级的 ID,我需要做两件事:

在删除父对象的方法中:

  1. 加载父级,将其标记为已删除并保存更改。这会阻止寄存器。
  2. 加载子项,将其标记为已删除并保存更改。
  3. 接受交易。

在添加孩子的方法中

  1. 加载父级。如果被阻塞,该方法等待直到寄存器空闲。
  2. 添加新的孩子。
  3. 接受更改。

确实不需要在上下文中加载父级来删除子级,这将是对数据库的额外查询。

如果父级不存在,则获取异常并且不需要执行任何其他操作,用户现在尝试添加新注册是因为父级已被删除。

如果父级存在,则可以添加子级。

所以我有两个问题。

  1. 使用事务删除父记录以确保删除所有子记录是个好主意吗?

  2. 如果事务是一个不错的选择,当父节点被阻塞时,数据库不允许使用父 ID 添加新记录或者我需要在方法中加载父节点的解决方案删除孩子?

【问题讨论】:

  • 您无法将父级标记为已删除并保存更改。 EF 将尝试删除记录,违反 FK 约束。还是通过在数据库字段中设置标志来标记为已删除?
  • 如果我没记错的话,如果我在一个事务中,当将父标记为已删除并进行第一次保存更改时,没有问题,因为我仍然不接受该事务。但这是理论上的,我没有做过测试。

标签: c# entity-framework transactions cascading-deletes


【解决方案1】:

事务不会推迟删除操作。数据库中没有类似“标记为已删除”的内容。当您将实体标记为已删除并执行SaveChanges 时,数据库中的记录将被删除。它总是发生在交易中。一旦记录即将被删除,就会检查 FK 约束,如果存在任何依赖记录,则会引发错误(除非约束的 ON DELETE 规则未定义其他选项)。使用 FK 约束时,您必须始终在删除父级之前删除子级。

如果您的描述准确,您可以简单地使用您害怕的第一种方法并关闭查询并将SaveChanges 转换为单个TransactionScope。它将以可序列化的隔离级别运行事务,这应确保在当前事务完成之前,没有其他事务能够将记录插入锁定的键范围(被查询锁定)。

虽然具有可序列化事务的解决方案可能有效,但它可能会带来其他问题 - 与应用程序中的其他事务发生死锁。因为重复失败的交易通常是最好的选择。如果您的系统具有如此大的并发负载,以至于删除事务可能“一直”失败,那么可能是时候彻底重新设计您的应用程序了。

【讨论】:

  • 事务范围内的可序列化隔离级别而不是readCommited?
  • 如果我决定使用重复失败的交易解决方案,尝试多少次才是一个好数字? 10、20、50……?并且数据库的性能没有受到太大影响?
  • TransactionScope 中的可序列化事务级别。可序列化事务对数据库有负面影响。影响取决于事务阻止的并发请求数。
  • 尝试次数没有任何“最佳”选择。这取决于你。
猜你喜欢
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多