EF Linq子层级查询按RespuestasVariablesDetalle.idNotaClinica过滤数据的实现方法
你当前使用的Any方法只能筛选出存在符合条件子节点的父级实体,不会自动过滤掉嵌套结构中不符合条件的子节点,这是EF/EF Core查询的默认行为,以下是两种可行的实现方案:
方案1:数据库端投影(推荐,效率最高)
直接在LINQ查询阶段就构造目标结果结构,所有过滤逻辑都在数据库执行,不会拉取冗余数据,性能最优:
int targetIdNotaClinica = 5; var visita = db.NotasClinicas // 先筛选存在符合条件的NotaClinica记录 .Where(nc => nc.Visitas.Visitas_Variable_Tipo .Any(vvt => vvt.Variables_Tipo.Variables .Any(v => v.Respuestas_Variables .Any(rr => rr.RespuestasVariablesDetalle .Any(d => d.idNotaClinica == targetIdNotaClinica))))) // 逐层投影并过滤嵌套节点,整个过程在数据库端执行 .Select(nc => nc.Visitas) .Select(v => new Visita // 替换为你实际的Visitas实体类名 { id = v.id, nombre = v.nombre, status = v.status, VisitasVariableTipo = v.Visitas_Variable_Tipo.Select(vvt => new VisitasVariableTipo // 替换为对应实体类名 { id = vvt.id, idVariableTipo = vvt.idVariableTipo, VariablesTipo = new VariablesTipo // 替换为对应实体类名 { id = vvt.Variables_Tipo.id, titulo = vvt.Variables_Tipo.titulo, Variables = vvt.Variables_Tipo.Variables.Select(vr => new Variable // 替换为对应实体类名 { id = vr.id, respuesta = vr.respuesta, CatalogoDatosTipo = vr.CatalogoDatosTipo, Variables = vr.Variables, // 过滤符合条件的RespuestasVariables节点 RespuestasVariables = vr.Respuestas_Variables .Where(rr => rr.RespuestasVariablesDetalle.Any(d => d.idNotaClinica == targetIdNotaClinica)) .Select(rr => new RespuestasVariable // 替换为对应实体类名 { id = rr.id, idRespuestaTipoFirma = rr.idRespuestaTipoFirma, idVariable = rr.idVariable, // 最终过滤到目标idNotaClinica的明细节点 RespuestasVariablesDetalle = rr.RespuestasVariablesDetalle .Where(d => d.idNotaClinica == targetIdNotaClinica) .ToList() }).ToList() }).ToList() } }).ToList() }) .FirstOrDefault();
如果使用EF Core 7+版本,也可以用Filtered Include语法简化部分逻辑,多层嵌套场景下显式投影的兼容性和可控性更高。
方案2:全量查询后内存过滤(仅适合数据量极小的场景)
如果嵌套数据量非常小,也可以先拉取全量数据后在内存中过滤,代码更简洁但不适合大数据量场景:
int targetIdNotaClinica = 5; // 加载全量关联数据,数据量大时会产生大量冗余查询 var visita = db.NotasClinicas .Include(nc => nc.Visitas) .ThenInclude(v => v.Visitas_Variable_Tipo) .ThenInclude(vvt => vvt.Variables_Tipo) .ThenInclude(vt => vt.Variables) .ThenInclude(v => v.Respuestas_Variables) .ThenInclude(rr => rr.RespuestasVariablesDetalle) .Where(nc => nc.Visitas.Visitas_Variable_Tipo .Any(vvt => vvt.Variables_Tipo.Variables .Any(v => v.Respuestas_Variables .Any(rr => rr.RespuestasVariablesDetalle .Any(d => d.idNotaClinica == targetIdNotaClinica))))) .First() .Visitas; // 内存中逐层过滤不匹配的子节点 foreach (var vvt in visita.VisitasVariableTipo) { foreach (var vr in vvt.VariablesTipo.Variables) { vr.RespuestasVariables = vr.RespuestasVariables .Where(rr => rr.RespuestasVariablesDetalle.Any(d => d.idNotaClinica == targetIdNotaClinica)) .ToList(); foreach (var rr in vr.RespuestasVariables) { rr.RespuestasVariablesDetalle = rr.RespuestasVariablesDetalle .Where(d => d.idNotaClinica == targetIdNotaClinica) .ToList(); } } }
两种方案优先选择方案1,仅当嵌套层级固定、数据量极小时考虑方案2,代码中的类名需替换为你实际定义的实体类名。
内容的提问来源于stack exchange,提问作者darkknightlullaby
相关产品推荐
相关产品推荐

