如何为LINQ查询中Include的关联表添加条件获取Table_J去重数据
LINQ查询Include关联表按指定列去重解决方案
你之前的写法无法生效的核心原因是EF Core的
Include/ThenInclude语法不支持直接在导航属性后附加Distinct、GroupBy这类聚合/去重操作,这类写法无法被EF Core正确解析为SQL语句,运行时要么报错要么不生效。
方案1:内存端二次处理(适合数据量小的场景)
先正常查询全量数据,加载完所有关联属性后,在内存中对Table_J集合按Title去重,代码示例:
// 先正常执行原有查询,加载所有需要的关联数据 var checkpoints = await DbContext.Table_B .Where(b => checkpointSourceIds.Contains(b.SourceId) && !b.IsArchived && !b.IsDisabled) .Include(c => c.Table_C) .ThenInclude(c => c.Table_D) .Include(c => c.Table_E) .ThenInclude(c => c.Table_F) .Include(c => c.Table_G) .ThenInclude(c => c.Table_H) .ThenInclude(c => c.Table_I) .Include(c => c.Table_J) .ThenInclude(c => c.Table_K) .Include(c => c.Table_L) .ThenInclude(c => c.Table_M) .Include(c => c.Table_N) .ThenInclude(c => c.Table_O) .Include(c => c.Table_P) .ThenInclude(c => c.Table_Q) .ToListAsync(); // 内存中对每个B对象的Table_J集合按Title去重,可根据需求调整排序规则确定保留哪条数据 foreach (var bItem in checkpoints) { bItem.Table_J = bItem.Table_J .GroupBy(j => j.Title) .Select(g => g.OrderBy(j => j.Id).First()) // 按Id升序取同Title下的第一条,可自定义排序 .ToList(); }
注意:如果后续需要对实体执行更新操作,不要直接修改跟踪状态下的Table_J集合,建议单独映射为DTO后再做去重处理。
方案2:投影查询(优先推荐,性能最优)
不直接返回实体类,通过Select投影为匿名类或自定义DTO,在投影逻辑中直接对Table_J做去重,去重逻辑会被翻译为SQL在数据库层面执行,不会加载多余的重复数据:
var checkpoints = await DbContext.Table_B .Where(b => checkpointSourceIds.Contains(b.SourceId) && !b.IsArchived && !b.IsDisabled) .Select(b => new { // 按需映射Table_B的字段 b.Id, b.SourceId, // 映射其他关联表字段 TableC = b.Table_C, TableD = b.Table_C.Table_D, TableE = b.Table_E, TableF = b.Table_E.Table_F, TableG = b.Table_G, TableH = b.Table_G.Table_H, TableI = b.Table_G.Table_H.Table_I, // 对Table_J按Title去重,同时加载关联的Table_K DistinctTableJ = b.Table_J .GroupBy(j => j.Title) .Select(g => g.OrderBy(j => j.Id).First()) .Select(j => new { j, j.Table_K }) .ToList(), TableL = b.Table_L, TableM = b.Table_L.Table_M, TableN = b.Table_N, TableO = b.Table_N.Table_O, TableP = b.Table_P, TableQ = b.Table_P.Table_Q }) .ToListAsync();
内容的提问来源于stack exchange,提问作者sm101
相关产品推荐
相关产品推荐

