5

我有一个来自数据库的项目集合,这些项目具有parentid值或空值。

这是我的班级设计:

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 映射的结构。

我尝试了这篇文章Recursive Hierarchical Joins in C# and LINQ 但如果 ParentId 为空,它会给我一个错误。

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

我如何实现这一目标?

4

3 回答 3

7

您可以使用这种方法:

  1. 从数据库中获取所有项目(不填写子项目)。
  2. 构建一个Lookup<int?,Item>父 ID 和具有该父 ID 的项目。
  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();
于 2013-08-03T07:05:11.080 回答
0

使用这个Node 类,你可以简单地做到这一点:

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

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

CreateTree 方法产生 1 个或多个根节点。如果您确定始终有 1 个根节点,则可以执行 rootNodes.Single() 来获取根。

于 2013-08-03T11:46:50.183 回答
0

您真的需要子项目的设置器吗?在 SQL 服务器上运行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 是保留字。)

于 2013-08-03T07:31:46.977 回答