EF Core - 在事务中强制执行命令的优先级

EF Core - Enforce priority in executing commands in a transaction

我想使用 EF Core 删除数据库中的 2 组数据。
所有代码都是假设的。

数据模型:

class Parent
{
    public int Id { get; set; }
}

class Child
{
    public int Id { get; set; }

    public int ParentId { get; set; }

    public virtual Parent Parent { get; set; }

    public bool Flag { get; set; }
}

假设我想删除所有带有 (ParentId=100) 和 (flag=false) 的 [Child] 记录,之后如果 (child.ParentId=100).length=0 则删除父项本身也是。
所以,这是服务 class:

class Service
{
    public void Command(int parentId)
    {
        Parent parent = GetParent(parentId);
        List<Child> children = GetChildren(parent);

        List<Child> toDelete = children.Where(x => !x.Flag).ToList();
        foreach(var child in toDelete)
        {
            var entry = DbContext.Entry(child);
            entry.State = EntityState.Deleted;
        }

        List<Child> remainChildren = children.Where(x => x.Flag).ToList();
        if (!remainChildren.Any())
        {
            var entry = DbContext.Entry(parent );
            entry.State = EntityState.Deleted;
        }

        SaveChanges();
    }
}

我有多个场景调用 Service.Command 方法。
因为我只调用 SaveChanges() 一次,所以我假设所有删除操作都将在单个事务中执行,当然它们的顺序是这样的:

  1. 删除子记录
  2. 删除父项

但是 EF 像这样向数据库发送查询:

  1. 删除父项
  2. 删除子记录

显然会抛出 ForeignKey 异常。

有什么方法可以强制 EF Core 执行查询以便我编写代码吗?

将 parent child 关系设置为在数据库级别级联删除。

一键查询所需数据...

var data = context.Parents.Where(p => p.ParentId == parentId)
  .Select(p => new 
  {
    Parent = p,
    ChildrenToRemove = p.Children.Where(c => c.Flag).ToList(),
    HasRemainingChildren = p.Children.Any(c => !c.Flag)
  }).Single();

然后只需检查数据并采取相应行动即可。如果没有剩余的 children,删除 parent 让 cascade 处理它。否则,只需从上下文中删除 children。

if(!data.HasRemainingChildren)
  context.Parents.Remove(data.Parent);
else
  context.Children.RemoveRange(data.ChildrenToRemove);

对于大实体,您可以通过仅选择 ID 然后将它们关联到新的实体实例、将它们附加到新的 DbContext,然后发出 Remove/RemoveRange 调用来进一步优化它。此选项是处理大量项目或 "big" 实体的优化,否则会导致大量数据通过网络传输。