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

标签 c# entity-framework asp.net-core ef-core-2.1

我想使用 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 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. 删除 parent
  2. 删除子记录

显然它会抛出 ForeignKey 异常。

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

最佳答案

在DB级别设置父子关系为级联删除。

一键查询所需数据...

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();

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

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

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

关于c# - EF Core - 在事务中强制执行命令的优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53259488/

相关文章:

c# - HasOptional 对应的 DataAnnotation 属性

c# - JWT token 过期在 Asp.Net Core API 中不起作用?

asp.net-core - 如何删除消息 "You are working with a preview version of the .NET Core SDK"

c# - 从图像中删除所有水平和垂直线

c# - LINQ 子查询

c# - 在 ServerControl 标签中添加子控件?

c# - 在 .Net 中将 Url 编码的表单数据转换为 JSON 有哪些选项

asp.net-mvc - 在 EF 6 中设置命令超时

c# - 如何将 Entity Framework 6 绑定(bind)到 KendoUI Grid

dependency-injection - asp.net 5依赖注入(inject)拦截调用方法