powered by simpleCommunicator - 2.0.18     © 2024 Programmizd 02
Map
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Как динамически загружать коллекций сущностей Entity Framework
19 сообщений из 19, страница 1 из 1
Как динамически загружать коллекций сущностей Entity Framework
    #40091295
Vlad__i__mir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Приложение ASP NET Core 3.1, использую EF Core 3.1.13.

Есть класс сущности БД, объект которого хранит коллекцию объектов этого же класса подчиненные ему. В свою очередь объекты, которые он хранит у себя в коллекции, аналогично могут иметь коллекции с другими объектами подчиненные им этого же класса:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
[Table("groupu")]
    public partial class Groupu
    {
        public Groupu()
        {
            Groupsusers = new HashSet<Groupsusers>();
            InverseGroupParents = new HashSet<Groupu>();
        }

        [Key]
        [Column("Id_Group")]
        public int IdGroup { get; set; }
        [DisplayName("Группа")]
        [Column(TypeName = "varchar(256)")]
        public string Name { get; set; }
        
        [DisplayName("Уровень группы")]
        [Column("Level")]
        public int? Level { get; set; }
        [DisplayName("Подчиняется")]
        [Column("Group_Parents_id")]
        public int? GroupParentsId { get; set; }
       
        [DisplayName("Подчиняется")]
        [ForeignKey(nameof(GroupParentsId))]
        [InverseProperty(nameof(Groupu.InverseGroupParents))]
        public virtual Groupu GroupParents { get; set; }
                    
        [InverseProperty(nameof(Groupu.GroupParents))]
        public virtual ICollection<Groupu> InverseGroupParents { get; set; }
    }



Задача обойти всех потомков текущей группы до самого низа. Я это делаю с помощью обхода графа в ширину. Прямые потомки текущего объекта загружаются при запросе на него в БД и в алгоритме я их могу перебрать:
Код: c#
1.
Groupu rootGroup = _context.Groupu.Include(g => g.InverseGroupParents).Include(g => g.GroupParents).FirstOrDefault(g => g.IdGroup==id);



Проблема в том, что не прямые потомки объекта, т.е. потомки потомков, которые хранятся в коллекциях прямых потомков, уже не загружаются, и я их перебрать уже не могу.

Как сделать, чтобы коллекции потомков подгружались?

Алгоритм, который используя для перебора потомков объекта:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
public List<Groupu> GetAllChildGroupsBFS(Groupu rootGroup, Groupu groupStart, Groupu goal)
        {
            // rootGroup - корневая группа
            // groupStart - начальный потомок
            // goal - пункт назначения, его нет

            // Список всех посещенных потомков
            List<Groupu> childGroupus = new List<Groupu>();

            // инициализируем очередь
            Queue<Groupu> queueGroupu = new Queue<Groupu>();
            // добавляем groupStart в очередь
            queueGroupu.Enqueue(rootGroup);

            while (queueGroupu.Count > 0)
            {
                // удаляем первый (верхний) элемент из очереди
                Groupu directChildgr = queueGroupu.Dequeue();
                //Добавляем посещенную вершину в список потомков
                childGroupus.Add(directChildgr);
                // rootGroup.InverseGroupParents - прямые потомки
                foreach (Groupu childgr in directChildgr.InverseGroupParents)
                {
                    // добавляем его в очередь
                    queueGroupu.Enqueue(childgr);
                
                }
            }
            // Возвращение списка потомков
            return childGroupus;
        }
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091298
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091299
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насколько я знаю, ЕФ не может делать рекурсивные запросы. Тут как раз случай, когда имеет смысл делать прямой SQL-запрос с рекурсивным CTE (если это MS SQL). В других диалектах наверняка что-то подобное тоже есть.

https://docs.microsoft.com/en-us/ef/core/querying/raw-sql
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091302
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro
https://docs.microsoft.com/ru-ru/ef/core/querying/related-data/eager

Тут не прокатит, наверное, - у него кол-во уровней произвольное может быть (судя по схеме БД)
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091309
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Тут не прокатит, наверное, - у него кол-во уровней произвольное может быть (судя по схеме БД)
Рекурсивно накатить ThenInclude раз двести )))

Вообще, если класс один и тот же, то что мешает грузануть все объекты в единую плоскую коллекцию, зачем обходить граф?
Понятно, что тогда элементам нужно знать свою принадлежность корневой сущности, но это обычно меньшее зло
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091311
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro
Вообще, если класс один и тот же, то что мешает грузануть все объекты в единую плоскую коллекцию, зачем обходить граф?

Тут изначально представление дерева в РБД сделано самым примитивным и неэффективным способом. Я бы посоветовал автору заглянуть в книгу "SQL Antipatterns" в главу "Naive Trees" - там описаны три намного лучших альтернативных способа.
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091312
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По-поводу рекурсивных запросов с CTE.

ORM linq2db позволяет делать таковые.

Если страшно вот так сразу перейти на сие божественное чудо с убогого EF (как же отказаться от поделия мелкософта?), то можно использовать библиотеку linq2db.EntityFrameworkCore .

Эта библиотека упомянута в списке EF Core Tools & Extensions .
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091317
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvik
ORM linq2db позволяет делать таковые.

Ради пары запросов менять весь ORM?
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091329
Vlad__i__mir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
fkthat
Shocker.Pro
Вообще, если класс один и тот же, то что мешает грузануть все объекты в единую плоскую коллекцию, зачем обходить граф?

Тут изначально представление дерева в РБД сделано самым примитивным и неэффективным способом. Я бы посоветовал автору заглянуть в книгу "SQL Antipatterns" в главу "Naive Trees" - там описаны три намного лучших альтернативных способа.


Тут уже поздно менять структуру - БД рабочая сданными, пользователи а ней уже работают
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091330
Vlad__i__mir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.Pro
fkthat
Тут не прокатит, наверное, - у него кол-во уровней произвольное может быть (судя по схеме БД)
Рекурсивно накатить ThenInclude раз двести )))

Вообще, если класс один и тот же, то что мешает грузануть все объекты в единую плоскую коллекцию, зачем обходить граф?
Понятно, что тогда элементам нужно знать свою принадлежность корневой сущности, но это обычно меньшее зло


Вот тут не понял, мне же нужны потомки одного конкретного объекта. Если я всех выгружу в List, то как мне это поможет.
Или вы имеете ввиду выгрузить всех, потом среди них найти нужного, а потом выбрать всех у кого в родителях стоит id нужного объекта?
А как тогда сохранить иерархию кто кому подчиняется внутри?
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091334
Vlad__i__mir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
petalvik
По-поводу рекурсивных запросов с CTE.

ORM linq2db позволяет делать таковые.

Если страшно вот так сразу перейти на сие божественное чудо с убогого EF (как же отказаться от поделия мелкософта?), то можно использовать библиотеку linq2db.EntityFrameworkCore .

Эта библиотека упомянута в списке EF Core Tools & Extensions .


Не знаком с данной библиотекой. Могли бы вы показать как в моем случае должен выглядеть запрос?
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091348
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad__i__mir
А как тогда сохранить иерархию кто кому подчиняется внутри?
Vlad__i__mir
Задача обойти всех потомков текущей группы до самого низа.
Если задача обойти, то с плоским списком это гораздо проще. Если задача какая-то другая, ее стоит озвучить
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091362
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad__i__mir
Тут уже поздно менять структуру - БД рабочая сданными, пользователи а ней уже работают

Тогда CTE. Впрочем, при желании, все эти паттерны из книги, что я выше упоминал ("Nested Sets", "Closure Table", и "Path Enumeration") можно реализовать и не меняя существующую структуру. Просто сделать нужную дополнительную таблица и триггера на таблицу с деревом, которая у тебя уже есть, для обновления этой дополнительной таблицы. Ни имеющийся код, ни имеющуюся схему менять при этом не придется.
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091372
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad__i__mir
Как сделать, чтобы коллекции потомков подгружались?


Забрать плоский список и собрать дерево на клиенте, не?


fkthat
Тогда CTE.


CTE вообще для другого. Чекайте: для фильтрации потомков и поиска предков.
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091379
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
CTE вообще для другого.

CTE не " вообще для другого", а еще и для другого. Но, в том числе и для этого.
https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver15#examples
(См. Пример "D")
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091521
Vlad__i__mir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.Pro
Vlad__i__mir
А как тогда сохранить иерархию кто кому подчиняется внутри?
Vlad__i__mir
Задача обойти всех потомков текущей группы до самого низа.
Если задача обойти, то с плоским списком это гораздо проще. Если задача какая-то другая, ее стоит озвучить


Обойти и сохранить их в коллекцию в том порядке, в котором они идут - от самого высокого до того кто внизу структуры.

В принципе при вашем варианте это наверное тоже можно реализовать - сперва найти прямых потомков по id, потом искать их потомков по id уже найденных потомков, получается тоже рекурсия, правда пока точно не знаю как её реализовать
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40091545
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad__i__mir
В принципе при вашем варианте это наверное тоже можно реализовать - сперва найти прямых потомков по id, потом искать их потомков по id уже найденных потомков, получается тоже рекурсия, правда пока точно не знаю как её реализовать

Блин. Я же тебе сказал - CTE. И ссылки дал. Вытягиваешь всех потомков рекурсивно одним запросом в коллекцию объектов. Потом эту коллекцию объектов обходишь. Обходить её чередой из 100500 запросов к серверу ты зашибешься.
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40092245
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad__i__mir,
Давно, лет 100 назад, была такая задача.
Сделал sql функцию, возвращающую таблицу (Id, ParentId) и параметром самый первый Id.
Она легко вызывается и ее можно поджойнить в linq to entity запросе.
...
Рейтинг: 0 / 0
Как динамически загружать коллекций сущностей Entity Framework
    #40092460
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ
Сделал sql функцию, возвращающую таблицу (Id, ParentId) и параметром самый первый Id.


Если я правильно понял, то второе поле это AncestorId
В общем-то да. Это всё, что нужно.
И вместо функции можно было сделать вьюху.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Как динамически загружать коллекций сущностей Entity Framework
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали тему (1): Анонимы (1)
Читали форум (1): Анонимы (1)
Пользователи онлайн (10): Анонимы (8), Bing Bot, Yandex Bot 1 мин.
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]