基于.NET Web Api与Dapper实现父子层级SQL表转Treeview JSON的问题
实现方案
1. 修正模型定义
你当前的模型字段设计有误,混淆了外键字段和子集合的定义,调整如下:
public class Region { public int RegionId { get; set; } public string RegionName { get; set; } // 对应表的外键字段,存储父级区域ID,和表字段名保持一致方便Dapper映射 public int? FK_RegionParentId { get; set; } // 子级区域集合,序列化后自动生成层级结构 public ICollection<Region> Children { get; set; } = new List<Region>(); }
你的表结构本身是标准的自关联设计,没有问题。
2. Dapper查询与树形组装逻辑
不需要多次查询数据库,一次拉取全量数据后在内存组装即可,实现逻辑非常简单:
// 第一步:用Dapper一次性查询所有区域数据 using var connection = new SqlConnection(你的连接字符串); var allRegions = connection.Query<Region>("SELECT * FROM Regions").ToList(); // 第二步:把所有数据存入字典,方便快速查找父级节点 var regionDict = allRegions.ToDictionary(r => r.RegionId); // 第三步:遍历组装层级 var rootRegions = new List<Region>(); foreach (var region in allRegions) { if (region.FK_RegionParentId == null) { // 无父级的节点为根节点 rootRegions.Add(region); } else { // 找到对应父级,将当前节点加入父级的子集合 if (regionDict.TryGetValue(region.FK_RegionParentId.Value, out var parentRegion)) { parentRegion.Children.Add(region); } } } // 第四步:直接返回根节点集合,序列化后就是层级结构的JSON return Ok(rootRegions);
3. 最终返回效果示例
[ { "regionId": 1, "regionName": "Europe", "fk_RegionParentId": null, "children": [ { "regionId": 4, "regionName": "France", "fk_RegionParentId": 1, "children": [] } ] }, { "regionId": 2, "regionName": "Asia", "fk_RegionParentId": null, "children": [ { "regionId": 6, "regionName": "China", "fk_RegionParentId": 2, "children": [ {"regionId":8,"regionName":"Hong Kong","fk_RegionParentId":6,"children":[]}, {"regionId":9,"regionName":"Beijing","fk_RegionParentId":6,"children":[]}, {"regionId":10,"regionName":"Shanghai","fk_RegionParentId":6,"children":[]} ] }, { "regionId":5, "regionName":"India", "fk_RegionParentId":2, "children":[] } ] }, { "regionId":3, "regionName":"Africa", "fk_RegionParentId":null, "children":[ {"regionId":7,"regionName":"Zimbabwe","fk_RegionParentId":3,"children":[]} ] } ]
补充说明
- 你之前返回的父级ID全为null,就是因为模型字段名和表字段不匹配,Dapper无法自动映射,修正字段名即可解决
- 这个方案性能远高于EF的递归延迟加载,只要全量数据不超过十万级都不会有性能问题
- 如果不需要返回空的children集合,可以在JSON序列化配置里开启忽略空集合的规则即可
内容的提问来源于stack exchange,提问作者sula1337
相关产品推荐
相关产品推荐

