【问题标题】:Selecting a specific Task and its ChildTasks recursively from EF core从 EF 核心递归地选择特定任务及其子任务
【发布时间】:2020-06-08 12:28:16
【问题描述】:

我有一个包含相同类型子项的 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();

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

另外,如果这是一个好的设计,请告诉我,或者我是否必须更改它。

【问题讨论】:

标签: c# linq ef-core-3.1


【解决方案1】:

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 Server,您可以使用 CTE's)。

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

【讨论】:

  • 找到了一种递归获取项目的方法:stackoverflow.com/a/42680957/362261
  • @John 是的,它基本上以递归方式完成了我在此处编写的操作,您也可以使用简单的 while 循环来实现。但它仍然会在每个级别发出一个请求。
  • 你能用那个解决方案更新你的答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多