EF核心-在事务中执行命令时强制执行优先级



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

数据模型:

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

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

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

但EF向数据库发送查询,如下所示:

  1. 删除父项
  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();

然后,这只是一个检查数据并采取相应行动的问题。如果没有剩余的子级,请删除父级并由cascade处理。否则,只需从上下文中删除子级即可。

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

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

最新更新