Оптимизация или объединение запросов EF Core 3 - PullRequest
1 голос
/ 27 марта 2020

У меня есть sql база данных, содержащая таблицу связей между различными точками. Теперь я хочу найти все точки, которые так или иначе связаны с данной точкой. Я хочу получить полное дерево соединений. Я реализовал класс Node, который содержит точку и ее входы и выходы (другие точки). Метод GetContainedTree (List connectionsTable, int initialPoint) использует connectionTable, чтобы найти все подключенные точки и вернуть их в качестве узла.

public class Connection
    {
        public int SourcePoint { get; set; }
        public int DestinationPoint { get; set; }
    }

    public class Node
    {
        public int Point { get; set; }
        public List<int> Inputs { get; set; }
        public List<int> Outputs { get; set; }

        public override string ToString()
        {
            string desc = "Name: " + Point + "\n";
            desc += "\nInputs:\n";
            foreach(int i in Inputs)
            {
                desc += i.ToString() + "\n";
            }
            desc += "\nOutputs:\n";
            foreach (int o in Outputs)
            {
                desc += o.ToString() + "\n";
            }
            return desc;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Connection> connectionTable = new List<Connection>();

            // connection tree on
            connectionTable.Add(new Connection() { SourcePoint = 1, DestinationPoint = 2 });
            connectionTable.Add(new Connection() { SourcePoint = 1, DestinationPoint = 3 });
            connectionTable.Add(new Connection() { SourcePoint = 3, DestinationPoint = 4 });
            connectionTable.Add(new Connection() { SourcePoint = 2, DestinationPoint = 4 });
            connectionTable.Add(new Connection() { SourcePoint = 4, DestinationPoint = 5 });

            // connection tree two
            connectionTable.Add(new Connection() { SourcePoint = 6, DestinationPoint = 7 });
            connectionTable.Add(new Connection() { SourcePoint = 7, DestinationPoint = 8 });
            connectionTable.Add(new Connection() { SourcePoint = 7, DestinationPoint = 9 });
            connectionTable.Add(new Connection() { SourcePoint = 7, DestinationPoint = 10 });
            connectionTable.Add(new Connection() { SourcePoint = 9, DestinationPoint = 11 });


            List<Node> tree1 = GetContainingTree(connectionTable, 4);
            List<Node> tree2 = GetContainingTree(connectionTable, 11);

            Console.WriteLine("Tree One:");
            foreach(Node n in tree1)
            {
                Console.WriteLine(n);
            }

            Console.WriteLine("Tree Two:");
            foreach (Node n in tree2)
            {
                Console.WriteLine(n);
            }


        }

        private static List<Node> GetContainingTree(List<Connection> connectionsTable, int startingPoint)
        {
            List<int> pointsToSearch = new List<int>() { startingPoint };
            List<Node> nodes = new List<Node>();

            while(pointsToSearch!=null && pointsToSearch.Count>0)
            {
                foreach(int pointToSearch in pointsToSearch)
                {
                    Node node = new Node() { Point = pointToSearch };
                    // search for outputs
                    var outputs = from connection in connectionsTable
                                  where connection.SourcePoint == pointToSearch
                                  select connection.DestinationPoint;

                    // search for inputs
                    var inputs = from connection in connectionsTable
                                 where connection.DestinationPoint == pointToSearch
                                 select connection.SourcePoint;

                    node.Inputs = inputs.ToList();   // execute the query on db server
                    node.Outputs = outputs.ToList();  // execute the query on db server

                    nodes.Add(node);
                }


                // update the pointsToSearch
                var allPointsInNodes = nodes.SelectMany(n => n.Inputs);
                allPointsInNodes.Union(nodes.SelectMany(n => n.Outputs));

                // remove all found node names
                pointsToSearch = allPointsInNodes.Where(p => !nodes.Select(n => n.Point).ToList().Contains(p))
                                                 .Distinct()
                                                 .ToList();
            }

            return nodes;
        }
    }

Вывод:

Tree One:
Name: 4

Inputs:
3
2

Outputs:
5

Name: 3

Inputs:
1

Outputs:
4

Name: 2

Inputs:
1

Outputs:
4

Name: 1

Inputs:

Outputs:
2
3

Tree Two:
Name: 11

Inputs:
9

Outputs:

Name: 9

Inputs:
7

Outputs:
11

Name: 7

Inputs:
6

Outputs:
8
9
10

Name: 6

Inputs:

Outputs:
7

Мое решение работает, но оно использует много индивидуально выполненных запросов к базе данных. Я хотел бы объединить как можно больше этих запросов, чтобы добиться большей производительности. Есть ли способ объединить логи c GetContainedTree (...) в один запрос? Мне все равно, нужно ли использовать синтаксис запроса или метода.

Я думаю, что было бы возможно объединить этот запрос с серверной функцией на сервере sql, но я хочу оставить свободу для изменения мой движок базы данных позже.

Большое спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...