EF Core中Include内用Lambda过滤关联集合报错,求正确实现方案
问题:查询关联激活状态ModelB的ModelA并仅加载激活项
实体类定义:
public class ModelA { public int Id { get; set; } public string Name { get; set; } public List<ModelB> ModelBClass { get; set; } } public class ModelB { public int Id { get; set; } public int ModelAId { get; set; } public ModelA modelA { get; set; } public bool IsActive { get; set; } }
需求:查询所有关联的ModelB中IsActive为true的ModelA,且仅加载这些激活状态的ModelB。
错误写法及报错:
_dbContext.ModelA.Include(c=>c.ModelBClass.Where(d=>d.IsActive == true)).ToListAsync();
运行时报错:Lambda expression used inside Include is not valid
解决方案
方法1:EF Core 5.0+ 过滤Include(推荐)
若项目使用EF Core 5.0及以上版本,官方支持直接对关联集合过滤,写法如下:
await _dbContext.ModelA .Include(a => a.ModelBClass.Where(b => b.IsActive)) .Where(a => a.ModelBClass.Any(b => b.IsActive)) // 仅保留包含激活ModelB的ModelA .ToListAsync();
若需保留所有ModelA(即使无激活ModelB,对应
ModelBClass为空集合),可移除Where过滤行。
方法2:投影查询(兼容所有EF版本)
如果EF版本低于5.0,或需要更灵活的控制,可通过投影构造目标对象:
await _dbContext.ModelA .Where(a => a.ModelBClass.Any(b => b.IsActive)) .Select(a => new ModelA { Id = a.Id, Name = a.Name, ModelBClass = a.ModelBClass.Where(b => b.IsActive).ToList() }) .ToListAsync();
该方式通过Select手动筛选激活的ModelB,兼容性强,适用于所有EF版本。
方法3:显式加载(分步场景)
若已加载ModelA集合,需为其追加加载激活的ModelB,可使用显式加载:
var modelAs = await _dbContext.ModelA.ToListAsync(); foreach (var a in modelAs) { await _dbContext.Entry(a) .Collection(a => a.ModelBClass) .Query() .Where(b => b.IsActive) .LoadAsync(); }
此方式适合分步骤加载数据的场景,但性能不如一次性查询高效。
内容的提问来源于stack exchange,提问作者Code Boy
相关产品推荐
相关产品推荐

