C# ASP.NET Web API 实现员工经理层级树形JSON输出咨询
实现员工层级树形JSON输出方案
1 调整实体类定义
首先给EmployeeHierarchy实体类新增下级员工集合属性,用于嵌套存储子节点:
public class EmployeeHierarchy { public int EmployeeId { get; set; } public string EmployeeName { get; set; } public int? ManagerId { get; set; } public string Position { get; set; } // 新增下级员工集合,初始化避免空引用异常 public List<EmployeeHierarchy> Subordinates { get; set; } = new List<EmployeeHierarchy>(); }
2 扁平数据转树形结构核心逻辑
调用存储过程拿到全部扁平化层级数据后,通过字典快速映射构建嵌套结构,无需递归,性能更高:
// 调用存储过程获取全部层级的扁平员工数据 List<EmployeeHierarchy> flatEmployeeList = dbContext.Database .SqlQuery<EmployeeHierarchy>("EXEC GetEmployeeHierarchy") .ToList(); // 构建员工ID映射字典,加快查找速度 var employeeDict = flatEmployeeList.ToDictionary(e => e.EmployeeId); // 存储最终的根节点(最高级无上级的管理人员) List<EmployeeHierarchy> treeRoot = new List<EmployeeHierarchy>(); foreach (var emp in flatEmployeeList) { // 有上级且上级存在,就把当前员工加入上级的下级集合 if (emp.ManagerId.HasValue && employeeDict.TryGetValue(emp.ManagerId.Value, out var manager)) { manager.Subordinates.Add(emp); } // 无上级即为根节点 else { treeRoot.Add(emp); } }
3 完整API接口示例
public class EmployeeController : ApiController { [HttpGet] [Route("api/employee/hierarchy")] public IHttpActionResult GetHierarchyTree() { try { using (var dbContext = new YourDbContextName()) { // 1. 取扁平数据 List<EmployeeHierarchy> flatEmployeeList = dbContext.Database .SqlQuery<EmployeeHierarchy>("EXEC GetEmployeeHierarchy") .ToList(); // 2. 构建字典 var employeeDict = flatEmployeeList.ToDictionary(e => e.EmployeeId); // 3. 组装树形结构 List<EmployeeHierarchy> treeRoot = new List<EmployeeHierarchy>(); foreach (var emp in flatEmployeeList) { if (emp.ManagerId.HasValue && employeeDict.ContainsKey(emp.ManagerId.Value)) { employeeDict[emp.ManagerId.Value].Subordinates.Add(emp); } else { treeRoot.Add(emp); } } return Ok(treeRoot); } } catch (Exception ex) { return InternalServerError(ex); } } }
4 解决JSON循环引用报错问题
因为子节点逻辑上属于父节点,直接序列化会触发循环引用错误,需要在App_Start/WebApiConfig.cs的Register方法中添加序列化配置:
// 使用Newtonsoft.Json的配置 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; // 如果是ASP.NET Core使用System.Text.Json的配置 builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; });
注意事项
- 存储过程需要返回全量员工层级数据,不能过滤或分页,否则会丢失节点无法构建完整树
- 如果员工数据量超过1000条,建议缓存构建完成的树结构,避免每次请求重复计算
内容的提问来源于stack exchange,提问作者Coder-Persona
相关产品推荐
相关产品推荐

