如何用LINQ根据子ID递归获取所有URS_Types父级节点?
递归获取分类的所有父级层级解决方案
问题背景
类型类定义如下:
public partial class URS_Types { [Key] public int ID { get; set; } public string TypeName { get; set; } public int? ParentID { get; set; } }
需要编写一个方法,接收类型ID,通过ParentID依次获取该类型的所有父级分类,直到没有上级为止。
尝试过以下代码,但由于join语句只能固定关联层级,仅能返回第一个类型名称,无法获取所有层级的父级:
var types = GetURS_Types(); var test = from type in types where type.ID == id join type2 in types on type.ParentID equals type2.ID join type3 in types on type2.ParentID equals type3.ID select type.TypeName;
可行解决方案
方案1:循环遍历(推荐)
先将所有类型存入字典以实现O(1)快速查找,然后从目标ID开始循环向上追溯父级,直到没有上级为止:
public List<string> GetAllParentTypeNames(int targetId) { // 将所有类型转为字典,键为ID,方便快速查找 var typeDictionary = GetURS_Types().ToDictionary(t => t.ID); var parentTypeNames = new List<string>(); int? currentTypeId = targetId; while (currentTypeId.HasValue) { if (typeDictionary.TryGetValue(currentTypeId.Value, out var currentType)) { // 检查当前类型是否有父级 if (currentType.ParentID.HasValue && typeDictionary.TryGetValue(currentType.ParentID.Value, out var parentType)) { parentTypeNames.Add(parentType.TypeName); // 切换到父级ID,继续向上查找 currentTypeId = parentType.ParentID; } else { // 没有父级,退出循环 break; } } else { // 找不到当前ID对应的类型,退出循环 break; } } return parentTypeNames; }
方案2:递归实现
如果分类层级不会很深,也可以用递归方式实现:
public List<string> GetAllParentTypeNamesRecursive(int targetId) { var allTypes = GetURS_Types().ToList(); var parentTypeNames = new List<string>(); void TraverseUp(int? currentId) { if (!currentId.HasValue) return; var currentType = allTypes.FirstOrDefault(t => t.ID == currentId.Value); if (currentType == null) return; if (currentType.ParentID.HasValue) { var parentType = allTypes.FirstOrDefault(t => t.ID == currentType.ParentID.Value); if (parentType != null) { parentTypeNames.Add(parentType.TypeName); // 递归查找父级的父级 TraverseUp(parentType.ParentID); } } } TraverseUp(targetId); return parentTypeNames; }
说明
- 循环遍历方案更高效,尤其是数据量大或层级较深时,字典的快速查找能避免多次遍历集合的开销,同时也不会出现递归可能导致的栈溢出问题。
- 递归方案代码更简洁,但仅适合层级较浅的场景。
内容的提问来源于stack exchange,提问作者beeeeeeeeeen
相关产品推荐
相关产品推荐

