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

EF Core中LINQ关联三表查询返回带嵌套列表DTO的实现方法

问题解决方法

你当前使用连续Inner Join的写法会导致单条组织记录按关联部门数拆成多行重复结果,无法直接在投影中填充子列表,需要调整查询结构使用GroupJoin处理一对多关联,EF Core会将整个查询翻译成单条SQL执行,不会产生N+1查询问题。

推荐写法(无导航属性版本,适配你当前的表结构设计)

不需要额外配置实体导航属性,直接修改查询逻辑即可,TODO位置替换为对应子集合投影,完整代码如下:

var organizationInfo = (from org in _dbContext.Organizations
                        where org.Id.ToUpper() == id.ToUpper()
                        orderby org.CreatedOn ascending
                        // 分组关联组织-部门中间表
                        join orgDept in _dbContext.OrganizationDepartments 
                            on org.Id equals orgDept.OrganizationId 
                            into orgDeptList
                        select new OrganizationDto
                        {
                            Id = org.Id,
                            OrganizationName = org.OrganizationName,
                            Logo = org.Logo,                                 
                            IsActive = org.IsActive,
                            // TODO位置的赋值逻辑
                            OrganizationDepartments = orgDeptList
                                .Join(
                                    _dbContext.Departments,
                                    od => od.DepartmentId,
                                    dept => dept.Id,
                                    (od, dept) => new OrganizationDepartmentDto
                                    {
                                        OrganizationId = org.Id,
                                        OrganizationName = org.OrganizationName,
                                        DepartmentId = dept.Id,
                                        DepartmentName = dept.DepartmentName
                                    }
                                ).ToList()
                        })
                    // 按ID查询单条记录,必须加这个方法取单个实例
                    .FirstOrDefault();

简化写法(已配置实体导航属性时使用)

如果你的EF实体已经配置了Organization->OrganizationDepartments->Department的级联导航关系,可以用Include+投影的写法,代码更简洁:

var organizationInfo = _dbContext.Organizations
    .Include(o => o.OrganizationDepartments)
        .ThenInclude(od => od.Department)
    .Where(o => o.Id.ToUpper() == id.ToUpper())
    .OrderBy(o => o.CreatedOn)
    .Select(o => new OrganizationDto
    {
        Id = o.Id,
        OrganizationName = o.OrganizationName,
        Logo = o.Logo,
        IsActive = o.IsActive,
        OrganizationDepartments = o.OrganizationDepartments
            .Select(od => new OrganizationDepartmentDto
            {
                OrganizationId = o.Id,
                OrganizationName = o.OrganizationName,
                DepartmentId = od.Department.Id,
                DepartmentName = od.Department.DepartmentName
            }).ToList()
    })
    .FirstOrDefault();

注意事项

  • 上述两种写法都会被EF Core翻译成单条SQL执行,不会产生重复的组织主记录,也不会触发多次数据库查询
  • 如果你需要过滤掉没有关联任何部门的组织,可以在投影前加Where(org => orgDeptList.Any())条件即可
  • 数据库如果使用大小写不敏感的排序规则(大部分业务系统默认配置),可以去掉Id.ToUpper()的转换,进一步利用索引提升查询效率

内容的提问来源于stack exchange,提问作者mnu-nasir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:45:42