You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 10:09:02