EF Core 2.0 does not load related entities when using where condition

.net-core c# entity-framework entity-framework-core

Question

I have an entity called Category that has a recursive relationship like this:

public class Category
    {
        public int CategoryId { get; set; }
        public int? ParentCategoryId { get; set; }
        public string Description { get; set; }

        public Category ParentCategory { get; set; }
        public ICollection<Category> Children { get; set; }
        public ICollection<ProductCategory> Products { get; set; }

        public Category()
        {
            Products = new List<ProductCategory>();
            Children = new List<Category>();
        }
    }

I'm having trouble understanding why this code

return await Context.Set<Category>()
                .Where(c => c.CategoryId == id)
                .OrderBy(c => c.Description)
                .ToListAsync();

is returning only the filtered category without its children and this query:

return await Context.Set<Category>()
                .OrderBy(c => c.Description)
                .ToListAsync();

is returning all the categories with the related children of each one. If I add an .Include(c => c.Children) to the filtered results, it returns what i'm looking for.

The main thing is that I want to understand why are those queries returning different result in terms of the children categories.

1
1
5/25/2018 7:33:52 PM

Accepted Answer

The first query:

return await Context.Set<Category>()
            .Where(c => c.CategoryId == id)
            .OrderBy(c => c.Description)
            .ToListAsync();

Is not returning Children because you are only loading the Category that matches the id provided from the database. If you want the children you need to Include(c => c.Children)

The second query:

return await Context.Set<Category>()
            .OrderBy(c => c.Description)
            .ToListAsync();

Has no filter, so EF Core is loading all Categories from the database. This contains the children because those entities get loaded as "parent" objects as well, so Entity will map the Navigation property using foreign keys since the entities are already being tracked in the Context.

As an example, if you did this:

Category parentCategory = await Context.Set<Category>()
        .SingleOrDefaultAsync(c => c.CategoryId == id);

List<Category> childCategories = await Context.Set<Category>()
        .Where(c => c.ParentCategoryId == parentCategory.CategoryId)
        .ToListAsync();

Then parentCategory would have its Children property populated, even though you didn't Include() them, but because the Entities were all being tracked within the scope of the same DbContext the relationship is mapped. In the above code, if you put a breakpoint on the second statement and inspected parentCategory, you would see that its Children property has no items until after you execute the second statement.

3
5/25/2018 8:08:02 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow