Создать упрощенный запрос для вложенных данных в одной таблице (.NET Core) - PullRequest
2 голосов
/ 30 октября 2019

У меня есть таблица типа:

Steps
 - id
 - name
 - parendId

parentId указывает на id в той же таблице.

Основная проблема в том, что у меня есть 3 уровня вложенности ...

Я хочу вывод, подобный этому:

step: {
    id: 1,
    name: 'step 1'
    childs: [
        {
            id: 2
            name: 'child lvl 1',
            childs: [
               {
                  id: 3,
                  name: 'child lvl 2'
                  childs: [...]
               }, ...
            ]
        }, ...
    ]
}

Так что в моем приложении у меня есть что-то вроде этого:

var parents =  _apiDbContext.StepResult
               .ToList();

foreach (var parent in parents) {
    var childs = _apiDbContext.StepResult
               .Where(s => s.StepParent == parent.Id)
               .ToList();

    foreach (var child in childs) {
         var childsLvl2 = _apiDbContext.StepResult
               .Where(s => s.StepParent == child.Id)
               .ToList();

         // ... One more level
    }
}

Это минимальный код, например, если я делаю некоторые ошибкипожалуйста, дайте мне знать.

Так что можно сделать это с помощью одного запроса или некоторой "магии" в ядре .net.

Это прекрасно работает, но убивает производительность ... Так что любой советбудет полезно.

Спасибо!

Ответы [ 3 ]

1 голос
/ 30 октября 2019

Попробуйте следующий рекурсивный код, который будет работать с любым количеством уровней

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication139
{
    class Program
    {
        static List<Step> steps = new List<Step>();
        static void Main(string[] args)
        {
            Tree root = new Tree();
            int rootId = 0;
            GetRecursive(rootId, root);
        }
        static void GetRecursive(int parentId, Tree parent)
        {
            foreach(Step step in steps.Where(x => x.id == parentId))
            {
                parent.step = step;
                if (parent.children == null) parent.children = new List<Tree>();
                Tree child = new Tree();
                parent.children.Add(child);
                GetRecursive(step.id, child);
            }
        }
    }
    public class Step
    {
       public int id { get;set;}
       public string name { get;set;}
       public int parendId { get; set; }
    }
    public class Tree
    {
        public List<Tree> children { get; set; }
        public Step step { get; set; }
    }
}
1 голос
/ 30 октября 2019

Я бы выделил все строки сразу в плоскую структуру данных, а затем загрузил бы ее в желаемую древовидную структуру. Это даст вам хорошее представление о том, как этого добиться:

//declare a class to hold your data
public class step
{
    public int id { get; set; }
    public string name { get; set; }
    public int? parentId { get; set; }
    public List<step> childs { get; set; }
}

public void loadSteps()
{
    var steps = new List<step>();

    //instead of doing this load from your db
    steps.Add(new step { id = 1, name = "t1", parentId = null });
    steps.Add(new step { id = 2, name = "t2", parentId = 1 });
    steps.Add(new step { id = 3, name = "t3", parentId = 2 });
    steps.Add(new step { id = 4, name = "t4", parentId = 1 });
    steps.Add(new step { id = 5, name = "t5", parentId = 1 });
    steps.Add(new step { id = 6, name = "t6", parentId = null });
    steps.Add(new step { id = 7, name = "t7", parentId = 6 });

    //build the tree from the flat data
    var tree = BuildTree(steps);
}

//build the tree using linq (this could also be done with a queue or recursion
static List<step> BuildTree(List<step> items)
{
    items.ForEach(i => i.childs = items.Where(ch => ch.parentId == i.id).ToList());
    return items.Where(i => i.parentId == null).ToList();
}
0 голосов
/ 30 октября 2019

Вы можете создать дерево шагов с помощью одного запроса к базе данных:

var dbList = _apiDbContext.StepResult
               .ToList();

List<Steps> steps = dbList.Where(x => x.parentID == null).Select(x => new Steps { id = x.id, name = x.name }).ToList();
steps.ForEach(x => Sample(x, dbList));

public class Steps
{
    public int id { get; set; }
    public string name { get; set; }
    public List<Steps> childs { get; set; }
}
public void Sample(Steps step, List<DbSteps> dbList)
{
    var childs = dbList.Where(x => x.parentID == step.id);
    if (!childs.Any())
        return;

    step.childs = childs.Select(x => new Steps { id = x.id, name = x.name }).ToList();
    step.childs.ForEach(x => Sample(x, dbList));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...