使用where condition时,EF Core 2.0不会加载相关实体

时间:2018-05-25 19:05:26

标签: c# entity-framework .net-core entity-framework-core

我有一个名为Category的实体,它具有这样的递归关系:

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>();
        }
    }

我无法理解为什么会这个代码

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

仅返回已过滤的类别,但没有子项和此查询:

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

返回所有类别以及每个类别的相关子项。 如果我将.Include(c =&gt; c.Children)添加到过滤后的结果中,它会返回我正在寻找的内容。

主要的是,我想了解为什么这些查询会在子类别方面返回不同的结果。

1 个答案:

答案 0 :(得分:3)

第一个查询:

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

不返回Children,因为您只加载与数据库提供的id匹配的Category。如果您需要Include(c => c.Children)

所需的孩子

第二个问题:

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

没有过滤器,因此EF Core正在从数据库加载所有Categories。这包含子节点,因为这些实体也作为“父”对象加载,因此实体将使用外键映射Navigation属性,因为实体已在上下文中被跟踪。

例如,如果您这样做:

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();

然后parentCategory会填充Children属性,即使您没有Include(),但是因为实体都在同一{{1}的范围内被跟踪关系是映射的。在上面的代码中,如果在第二个语句上放置断点并检查DbContext,则在执行第二个语句之后,您会看到其parentCategory属性没有项目。