递归层次父子关系

本文关键字:父子关系 层次 递归 | 更新日期: 2023-09-27 18:25:58

我有一个来自parentid值或null的数据库的项集合。

这是我的课堂设计:

public class Item
{
public int id{get;set;}
public string Name{get;set;}
public int? ParentId{get;set;}
public List<Item> SubItems{get;set;}
}

我想从集合中构建一个项目的层次结构。假设一个集合是100个项目,我需要从中构建基于ParentId映射的结构。

我在C#和LINQ中尝试过这个帖子递归层次连接但如果ParentId为null,则会给我一个错误。

还尝试过通过递归检查父子关系C#来构建树类型列表,但这个解决方案也不适用于我

我该如何做到这一点?

递归层次父子关系

您可以使用这种方法:

  1. 从数据库中获取所有项目(不填充SubItems)
  2. 构建父id和具有该父id的项的Lookup<int?,Item>
  3. 循环浏览这些项,并使用查找将每个项与子项相关联

代码:

var items = // get from the database... (e.g. as a list)
var lookup = items.ToLookup(x => x.ParentId);
foreach (var item in items)
    item.SubItems = lookup[item.Id].ToList();

正如@EamonNerbonne在下面评论的那样,如果需要,您也可以获得根元素:

var roots = lookup[null].ToList();

使用此Node类,您可以简单地执行以下操作:

var flatListOfItems = GetItemsFromDatabase();
var rootNodes =Node<Item>.CreateTree(flatListOfItems, i => i.id, i => i.ParentId);

您的项不再需要子项,因为Node类具有子项和子项属性。(还有祖先、兄弟姐妹、等级等)。

CreateTree方法会产生一个或多个根节点。如果你确定总是有一个根节点,你可以执行rootNodes.Single()来获取根。

您真的需要一个子项的setter吗?在SQL server上运行Select*查询时,还要注意性能问题。

  public List<Item> SubItems{
  get
  {
   try{
        var validParents = db.items.Where(x=>x.ParentId!=null && x.ParentId.Equals(Id)); //db is your dbcontext
        if(validParents !=null)
        {
           return validParents.ToList(); 
        }else
        {
         return null;
        } 
        catch(Exception)
        {
          return null;
        }
   }

(注意:考虑将其添加到分部实体类中。永远不要将实体命名为"Item":)。Item是一个保留字。)