ASP.NET Core编写GET API获取指定员工到CEO的管理层级链
解决方案
现有代码问题分析
你当前的代码仅对员工表做了一次自连接,只能获取到指定员工的直接上级,无法实现向上递归查询到CEO的完整链路;同时直接将整张员工表加载到内存,当数据量较大时会出现严重的性能问题。
推荐方案:SQL Server 递归CTE实现(性能最优)
直接在数据库层通过递归公共表达式完成层级查询,避免全表数据拉取到应用侧,适合各种数据量场景。
递归查询SQL示例
-- 入参 @TargetEmpId 为你要查询的员工ID WITH EmpHierarchy AS ( -- 锚点:定位目标员工 SELECT Id, MngId, EmployeeName, 0 AS SortSeq FROM Employees WHERE Id = @TargetEmpId UNION ALL -- 递归向上查询上级,直到无上级(CEO) SELECT e.Id, e.MngId, e.EmployeeName, eh.SortSeq - 1 FROM Employees e INNER JOIN EmpHierarchy eh ON e.Id = eh.MngId ) -- 拼接为连续字符串,排序后得到从直接上级到CEO的顺序 SELECT STRING_AGG(EmployeeName, '') WITHIN GROUP (ORDER BY SortSeq) AS HierarchyChain FROM EmpHierarchy WHERE Id != @TargetEmpId -- 排除查询员工自身
如果你的SQL Server版本低于2017不支持STRING_AGG,可以将查询结果返回到C#侧再做字符串拼接。
API侧代码调整
通过EF Core执行原生SQL获取结果即可:
[Route("empLevel/{id}")] public IActionResult GetEmpHierarchy(int id) { // 校验员工是否存在 var empExists = entity.Employees.Any(e => e.Id == id); if (!empExists) { return NotFound("指定员工不存在"); } // 执行递归CTE查询 var result = entity.Employees .FromSqlRaw(@"WITH EmpHierarchy AS ( SELECT Id, MngId, EmployeeName, 0 AS SortSeq FROM Employees WHERE Id = {0} UNION ALL SELECT e.Id, e.MngId, e.EmployeeName, eh.SortSeq - 1 FROM Employees e INNER JOIN EmpHierarchy eh ON e.Id = eh.MngId ) SELECT STRING_AGG(EmployeeName, '') WITHIN GROUP (ORDER BY SortSeq) AS HierarchyChain FROM EmpHierarchy WHERE Id != {0}", id) .AsEnumerable() .FirstOrDefault()?.ToString() ?? string.Empty; return Ok(new { EmpId = id, HierarchyChain = result }); }
备选方案:C#内存递归实现(仅适合小数据量场景)
如果员工数据量极小(低于1000条),也可以在应用侧通过递归查询实现:
[Route("empLevel/{id}")] public IActionResult GetEmpHierarchy(int id) { var allEmps = entity.Employees.ToList(); var targetEmp = allEmps.FirstOrDefault(e => e.Id == id); if (targetEmp == null) { return NotFound("指定员工不存在"); } var chain = new List<string>(); var currentMngId = targetEmp.MngId; while (currentMngId != null) { var manager = allEmps.FirstOrDefault(e => e.Id == currentMngId.Value); if (manager == null) break; chain.Add(manager.EmployeeName); currentMngId = manager.MngId; } var result = string.Join("", chain); return Ok(new { EmpId = id, HierarchyChain = result }); }
边界情况说明
- 如果查询的员工本身就是CEO(
MngId为NULL),返回空字符串 - 若中间出现上级ID不存在的脏数据,自动终止查询返回已找到的层级链
内容的提问来源于stack exchange,提问作者Coder-Persona
相关产品推荐
相关产品推荐

