从 EF 核心递归选择特定任务及其 ChildTasks

Selecting a specific Task and its ChildTasks recursively from EF core

我有一个 TaskItem class,它有相同类型的子项:

public class TaskItem
{
    public Guid Id { get;set; }

    // Parent Task

    public TaskItem ParentTask { get; set; }

    public Guid? ParentTaskId { get; set; }

   //Child Tasks

    public ICollection<TaskItem > ChildTasks{ get; set; }
}

以平面列表的形式递归获取任务及其子任务:

var taskList =  taskDBContext.TaskItems.Include(c => c.ChildTasks)
                .Where(x => x.Id == taskId)
                .SelectMany(x => x.ChildTasks)
                .ToList();

问题是我总是得到一个任务,尽管这个任务有许多不同级别的孙子。我的方案是将特定父项及其子项和孙项加载为单个列表。

此外,请告诉我这是一个好的设计还是我必须更改它。

EF Core 不会以递归方式为您获取数据,您需要自己为每个级别获取数据:

var secondLevelx = taskDBContext.TaskItems
    .Where(x => x.Id == taskId)
    .SelectMany(x => x.ChildTasks)
    .SelectMany(x => x.ChildTasks)
    .ToList();

或:

var secondLevelx = taskDBContext.TaskItems
    .Where(x => taskList.Select(t=>t.Id).Contains(x.Id))
    .SelectMany(x => x.ChildTasks)
    .ToList();  

并在有结果时重复。

或者如果您的数据库支持,则编写递归 sql 查询(例如,对于 SQL 服务器,您可以使用 CTE's)。

UPD

如果您可以接受每个级别的请求(据我所知,您可以传递给查询的参数数量是有限的)并且您没有循环,您可以这样做:

var taskList = new List<TaskItem>();
var toQuery = new List<Guid> {taskId};

do
{
    var current = taskDBContext.TaskItems
        .Where(x => toQuery.Contains(x.Id))
        .SelectMany(x => x.ChildTasks)
        .ToList();
    taskList.AddRange(current);
    toQuery = current.Select(x => x.Id).ToList();
} while (toQuery.Any());