EF Core 3.1 如何编写LINQ实现主从表双向过滤并返回匹配主从记录
现有代码问题说明
- 语法错误:
Where(m => m.Category = 'foo')属于赋值操作,正确等值判断应该用==,且C#字符串需要用双引号包裹 - EF Core 3.1中
Include默认会加载主表关联的全部从表记录,不会自动应用后续Join逻辑中的过滤条件,所以就算关联了过滤后的从表,最终加载的MyDetails还是会包含已删除的记录 - 原写法的Join逻辑只实现了过滤「没有未删除从表的主表」的需求,没有实现从表数据过滤的需求
正确实现方案
方案1:投影查询(兼容EF Core 3.1,推荐)
直接通过Select投影需要的字段,手动过滤从表数据,同时加主表过滤条件,生成的SQL和需求完全等效:
var result = await dbContext.MyMasters .AsNoTracking() // 不需要跟踪实体可添加,提升查询性能 .Where(m => m.Category == "foo" && m.MyDetails.Any(d => !d.IsDeleted)) // 过滤掉所有从表都已删除的主表 .Select(m => new MyMaster { Id = m.Id, Category = m.Category, // 仅加载未标记删除的从表数据 MyDetails = m.MyDetails.Where(d => !d.IsDeleted).ToList() }) .ToListAsync();
方案2:过滤Include(仅EF Core 5.0及以上版本支持)
如果可以升级EF Core版本,可以用更简洁的过滤Include语法:
var result = await dbContext.MyMasters .AsNoTracking() .Where(m => m.Category == "foo" && m.MyDetails.Any(d => !d.IsDeleted)) // Include时直接指定关联数据的过滤条件 .Include(m => m.MyDetails.Where(d => !d.IsDeleted)) .ToListAsync();
内容的提问来源于stack exchange,提问作者Petr Felzmann
相关产品推荐
相关产品推荐

