EF Core 2.1未使用Include却加载关联属性的原因咨询
EF Core中导航属性自动填充与Include的使用场景
问题背景
我们在项目中使用Entity Framework Core 2.1.14,HouseholdMmbrPrfl与HouseholdMemberIncomes为一对多关系。执行以下两段代码时,生成的SQL不同,但都返回了关联属性:
// test1: 未使用Include var test1 = await _dbContext.HouseholdMmbrPrfl .Where(x => x.HouseholdMemberProfileId == memberId) .FirstOrDefaultAsync(); // test2: 使用Include var test2 = await _dbContext.HouseholdMmbrPrfl .Include(x => x.HouseholdMemberIncomes) .Where(x => x.HouseholdMemberProfileId == memberId) .FirstOrDefaultAsync();
test1仅查询HouseholdMmbrPrfl表,但导航属性HouseholdMemberIncomes已被填充;test2执行两次查询(分别针对主表和关联表)。我们未启用UseLazyLoadingProxies,且导航属性并非虚拟:
public List<HouseholdMemberIncome> HouseholdMemberIncomes { get; set; }
核心原因:EF Core的关系修复(Relationship Fixup)
test1中导航属性被自动填充,是EF Core的关系修复机制在起作用:
- 当当前
DbContext实例的一级缓存中,已经存在与HouseholdMmbrPrfl关联的HouseholdMemberIncome实体时,EF Core会自动将这些缓存的子实体填充到主实体的导航属性中。 - 这种情况下不会触发额外SQL查询,因为数据已经存在于上下文缓存里。
什么时候需要使用Include?
虽然关系修复能自动填充导航属性,但它依赖上下文缓存的存在,不可靠。必须使用Include的场景包括:
- 上下文无关联数据缓存时:如果是新的
DbContext实例,或者之前从未查询过对应的关联数据,不使用Include的话,导航属性会是null(或空集合,取决于属性初始化方式)。 - 确保主动加载关联数据:当你需要在查询主实体的同时,明确加载关联数据,避免后续因为缓存不存在导致导航属性为空的情况。
- 控制查询计划:使用
Include可以让EF Core生成明确的关联查询(EF Core 2.1中一对多默认是两次独立查询,后续版本支持合并为单查询),确保数据加载的确定性。
额外说明
你的场景中可以排除懒加载:懒加载要求导航属性为虚拟类型,且必须启用UseLazyLoadingProxies,而你的代码都不满足这两个条件,所以不存在懒加载触发的可能。
内容的提问来源于stack exchange,提问作者Paritosh
相关产品推荐
相关产品推荐

