我有一个名为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)添加到过滤后的结果中,它会返回我正在寻找的内容。
主要的是,我想了解为什么这些查询会在子类别方面返回不同的结果。
答案 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
属性没有项目。