EF Core:通过分页从大型子集合中断开连接删除

问题描述 投票:0回答:1

我的问题基于类似的问题,但增加了分页的复杂性。

public class Parent
{
    public Parent()
    {
        this.Children = new List<Child>();
    }

    public int Id { get; set; }

    public virtual ICollection<Child> Children { get; set; }
}

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

    public int ParentId { get; set; }

    public string Data { get; set; }
}

假设 Children 集合有 1000 条记录:

{ 1, 2, 3, ... 998, 999, 1000 }

public Parent Get(int parentId, int childrenPageSize)
{
    var existingParent = _dbContext.Parents
    .Where(p => p.Id == parentId)
    .Include(p => p.Children.Take(childrenPageSize))
    .AsNoTracking()
    .SingleOrDefault();
}

通过分页,我们只取前 10 个子项:

{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

用户然后在前端应用程序中编辑 Parent 对象,并删除集合中的 2 个子对象,然后单击“保存”以更新父对象:

{ 3, 4, 5, 6, 7, 8, 9, 10 }

我在存储库类中使用 Update 方法

public void Update(UpdateParentModel model)
{
    var existingParent = _dbContext.Parents
    .Where(p => p.Id == model.Id)
    .Include(p => p.Children)
    .SingleOrDefault();

    // Delete children
    foreach (var existingChild in existingParent.Children.ToList())
    {
        if (!model.Children.Any(c => c.Id == existingChild.Id))
            _dbContext.Children.Remove(existingChild);
    }
}

问题:当实体框架加载existingParent时,它会急切地加载1000个子级的整个集合。模型参数包含 8 个子项的集合,其中两个已被删除。我如何告诉实体框架仅删除已删除的 2 个子项?

注意:我想避免使用 ExecuteDelete、RawSQL 或存储过程。我需要能够调用 _dbContext.SaveChangesAsync()。

asp.net entity-framework asp.net-core asp.net-web-api entity-framework-core
1个回答
0
投票

UpdateParentModel
应包含
IEnumerable<int>
的属性,表示要删除的
Child
对象的 ID。然后,您可以附加一个已删除的新
Child
对象,仅使用为该可枚举属性中的每个 ID 值设置的 ID 值,从而无需从数据库加载任何内容。

您用于操作的模型不需要与它们所作用的一个或多个实体相匹配。以最有用/最高效的方式打包数据。

foreach( var childId in model.RemovedChildIDs )
{
    var entry = dbContext.Attach( new Child
    {
        Id = childId,
    } );

    entry.State = EntityState.Deleted;
}

…

dbContext.SaveChangesAsync();
© www.soinside.com 2019 - 2024. All rights reserved.