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



我有一个具有相同类型的子项的 TaskItem 类:

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查询(例如,对于SQL Server,您可以使用CTE(。

UPD

如果您可以按级别发出请求(也是 AFAIK,您可以限制可以传递给查询的参数数量(并且您没有周期,您可以执行以下操作:

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

最新更新