如何用C# LINQ实现分类与父分类的无限层级结构查询
实现无限层级分类结构的C# LINQ解决方案
需求说明
需要将分类表通过循环引用实现无限层级结构,目标展示结构如下:
Automotive - vehicle hire - Vehicle Sales Tyre's And Shocks - Tyres - dunlop - continental - Shocks - Gabriel - No Name
现有代码片段:
var category = _context.Category.Where(c.ParentCategoryId == 11).ToList();
分类表结构:
| CategoryID | ParentCategoryID | CategoryName |
|---|---|---|
| 1 | null | Automotive |
| 2 | 1 | Vehicle Hire |
| 3 | 1 | Vehicle Sales |
| 4 | 1 | Spares or Accessories |
| 5 | 1 | Automotive Associations |
| 6 | 1 | Financial Institutions |
| 7 | 1 | Health Care |
| 8 | 1 | Panelbeaters |
| 9 | 1 | Auto Glass |
| 10 | 1 | Mags or Rims |
| 11 | 1 | Tyre's And Shocks |
| 12 | 11 | Tyres |
| 13 | 11 | Shocks |
| 14 | 11 | Exhausts |
| 15 | 11 | Suspension Springs |
| 16 | 12 | Dunlop |
| 17 | 12 | Continental |
| 18 | 13 | Gabriel |
| 19 | 13 | No Name |
实现方案
1. 调整分类实体类
首先在Category实体中添加子分类集合属性,用于存储当前分类的下级节点:
public class Category { public int CategoryID { get; set; } public int? ParentCategoryID { get; set; } public string CategoryName { get; set; } // 子分类集合,初始化空列表避免空引用 public ICollection<Category> SubCategories { get; set; } = new List<Category>(); }
2. 递归构建无限层级结构
为了减少数据库查询次数,先一次性加载所有分类数据到内存,再通过递归方法构建层级:
// 一次性加载所有分类 var allCategories = _context.Category.ToList(); // 递归构建指定父ID的分类层级 List<Category> BuildCategoryHierarchy(int? parentId) { return allCategories .Where(c => c.ParentCategoryID == parentId) .Select(c => { // 递归加载当前分类的子分类 c.SubCategories = BuildCategoryHierarchy(c.CategoryID); return c; }) .ToList(); } // 构建根分类层级(ParentCategoryID为null的分类) var fullHierarchy = BuildCategoryHierarchy(null); // 若只需构建ParentCategoryID=11的分类层级,调用: // var targetHierarchy = BuildCategoryHierarchy(11);
3. 格式化输出层级结构
编写递归方法按要求格式输出层级:
void PrintCategoryHierarchy(List<Category> categories, int indentLevel = 0) { foreach (var category in categories) { // 根据层级生成缩进 var indent = new string(' ', indentLevel * 9); if (indentLevel > 0) { indent = indent.Substring(0, indent.Length - 1) + "- "; } Console.WriteLine($"{indent}{category.CategoryName}"); // 递归输出子分类 if (category.SubCategories.Any()) { PrintCategoryHierarchy(category.SubCategories, indentLevel + 1); } } } // 调用输出方法 PrintCategoryHierarchy(fullHierarchy);
4. 可选:用GroupJoin实现非递归构建(限固定层级)
如果确定分类层级是固定的,也可以用GroupJoin一次性关联父级和子级,但这种方式不支持无限层级:
var allCategories = _context.Category.ToList(); var fixedHierarchy = allCategories .Where(c => c.ParentCategoryID == null) .Select(c => new Category { CategoryID = c.CategoryID, ParentCategoryID = c.ParentCategoryID, CategoryName = c.CategoryName, SubCategories = allCategories .Where(sc => sc.ParentCategoryID == c.CategoryID) .Select(sc => new Category { CategoryID = sc.CategoryID, ParentCategoryID = sc.ParentCategoryID, CategoryName = sc.CategoryName, SubCategories = allCategories.Where(s => s.ParentCategoryID == sc.CategoryID).ToList() }) .ToList() }) .ToList();
内容的提问来源于stack exchange,提问作者Krivahn Doss
相关产品推荐
相关产品推荐

