Динамическая загрузка коллекций сущностей Entity Framework
Приложение ASP NET Core 3.1, использую EF Core 3.1.13.
Есть класс сущности БД, объект которого хранит коллекцию объектов этого же класса подчиненные ему. В свою очередь объекты, которые он хранит у себя в коллекции, аналогично могут иметь коллекции с другими объектами подчиненные им этого же класса:
[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; }
}
Задача обойти всех потомков текущей группы до самого низа. Я это делаю с помощью обхода графа в ширину. Прямые потомки текущего объекта загружаются при запросе на него в БД и в алгоритме я их могу перебрать:
Groupu rootGroup = _context.Groupu.Include(g => g.InverseGroupParents).Include(g => g.GroupParents).FirstOrDefault(g => g.IdGroup==id);
Проблема в том, что не прямые потомки объекта, т.е. потомки потомков, которые хранятся в коллекциях прямых потомков, уже не загружаются, и я их перебрать уже не могу.
Как сделать, чтобы коллекции потомков подгружались?
Алгоритм, который используя для перебора потомков объекта:
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;
}