Entity Framework get full tree of objects from database
There is such a structure of classes:
public class GroupModel { public int Id { get; set; } public string Title { get; set; } public string Description { get; set; } public int ParentGroupId { get; set; } public List<GroupModel> Groups { get; set; } = new List<GroupModel>(); [ForeignKey("ParentGroupId")] public GroupModel ParentGroup { get; set; } public List<BuildingModel> Buildings { get; set; } = new List<BuildingModel>(); } public class BuildingModel { public int Id { get; set; } public int GroupId { get; set; } public string Title { get; set; } public List<FlatModel> Flats { get; set; } = new List<FlatModel>(); [ForeignKey("GroupId")] public GroupModel Group { get; set; } } public class FlatModel { public int Id { get; set; } public int BuildingId { get; set; } public string Title { get; set; } [ForeignKey("BuildingId")] public BuildingModel Building { get; set; } }
A group can include both buildings and other groups. The root group refers to itself (Id = 0, ParentGroupId = 0). The question is how can I get a complete list of groups, buildings and Flats using the entity framework.
If I use this code:
var list = db.groups.Where(x => x.Id == 0) .Include(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ToList();
As a result, I get a complete tree (up to level 6, but I don’t need it anymore), but it will not include Buildings and Flats, respectively.
The question is how can I build a complete groups tree so that it also includes Buildings (and they included Flats).
I tried different combinations, but all of them do not work:
var list = db.groups.Where(x => x.Id == 0) .Include(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .Include(x => x.Buildings) .ThenInclude(x=>x.Flats) .ToList(); var list = db.groups.Where(x => x.Id == 0) .Include(x => x.Groups) .Include(x => x.Buildings) .ThenInclude(x=>x.Flats) .ThenInclude(x => x.Groups) .ThenInclude(x => x.Groups) .ToList(); var list = db.groups.Where(x => x.Id == 0) .Include(x => x.Groups) .Include(x => x.Buildings) .ThenInclude(x=>x.Flats) .Include(x => x.Groups) .Include(x => x.Buildings) .ThenInclude(x=>x.Flats) .Include(x => x.Groups) .Include(x => x.Buildings) .ThenInclude(x=>x.Flats) .ToList();
I believe this can be done by constructing the tree of groups only by the first code fragment, and then loading the all buildings from the database, and sorting them into groups, but this will not be very fast and not very correct.
I would suggest you that use LazyLoading
in that case so that you don’t need to deal with multiple Include
:
Lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed.
You can change LazyLoadingEnabled
:
this.Configuration.LazyLoadingEnabled = false//true;
For more info have a look at Loading Related Entities