【问题标题】:Recursive select via LINQ? [duplicate]通过LINQ递归选择? [复制]
【发布时间】:2012-03-29 15:57:28
【问题描述】:

可能重复:
linq to sql recursive query

我不得不通过 LINQ 为自引用表构建递归选择。

我使用这个类:

public class DivisionHierarchy
{
    public Division Division { get; set; }
    public IEnumerable<DivisionHierarchy> Divisions { get; set; }
}

我创建了这个函数,但不知何故它是无限的。

public IEnumerable<DivisionHierarchy> GetDivisionHierarchy(IEnumerable<Division> allDivisions, Division parentDivision)
{
    Guid? parentDivisionId = null;

    if (parentDivision != null)
         parentDivisionId = parentDivision.DivisionID;

    var childDivisions = allDivisions.Where(e => e.DivisionID == parentDivisionId);

    Collection<DivisionHierarchy> hierarchy = new Collection<DivisionHierarchy>();

    foreach (var div in childDivisions)
       hierarchy.Add(new DivisionHierarchy() { Division = div, Divisions = GetDivisionHierarchy(allDivisions, div) });

     return hierarchy;
}

任何线索我可以从哪里开始?

谢谢!

附:还有其他方法吗?


更新基于http://www.scip.be/index.php?Page=ArticlesNET18#AsHierarchy

我发现了我的错误。

有两件事要实现: 1. 根节点要在数据库下创建。

  1. 我稍微修改了代码。

    Guid divisionID = Guid.Parse("5b487b3d-e9be-413f-b611-2fd7491e0d0d"); // Hardcoded somehow
    var rootDivision = db.Divisions.Where(i => i.ID == divisionID).FirstOrDefault();
    var divisionHierarchy = GetDivisionHierarchy(db.Divisions.AsEnumerable(), rootDivision);
    

    ...

     public IEnumerable<DivisionHierarchy> GetDivisionHierarchy(IEnumerable<Division> allDivisions, Division parentDivision)
            {
                Guid? parentDivisionId = null;
    
                if (parentDivision != null)
                    parentDivisionId = parentDivision.ID;
    
                var childDivisions = allDivisions.Where(division => division.DivisionID == parentDivisionId);
    
                Collection<DivisionHierarchy> hierarchy = new Collection<DivisionHierarchy>();
    
                foreach (var div in childDivisions)
                {
                    DivisionHierarchy divisionHierarchy = new DivisionHierarchy();
                    divisionHierarchy.Division = div;
                    divisionHierarchy.Divisions = GetDivisionHierarchy(allDivisions, div);
                    hierarchy.Add(divisionHierarchy);
                }
    
                return hierarchy;
            }
    

【问题讨论】:

  • 您是否尝试过至少在堆栈溢出时搜索答案? stackoverflow.com/questions/4072166/linq-to-sql-recursive-query 看起来像直接复制品。
  • @Ruslan 它没有我需要的答案。我需要将整棵树放入某个变量中。
  • @Peretz 如果您需要全部内容,那么您最好直接拉下列表并将其映射到内存中的一棵树。

标签: c# .net linq recursive-query


【解决方案1】:

我会以非递归方式加载分区,然后在代码中设置递归关系。这是一个例子,它以一种懒惰的方式做到这一点

public class Division
{
    public int ID { get; set; }
    public int DivisionID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    private static List<Division> _divisions;
    public static List<Division> Divisions
    {
        get
        {
            if (_divisions == null) {
                LoadAndSetUpDivisionsHierarchy();
            }
            return _divisions;
        }
    }

    private static Dictionary<int, Division> _divisionsByID;
    public static Dictionary<int, Division> DivisionsByID
    {
        get
        {
            if (_divisionsByID == null) {
                LoadAndSetUpDivisionsHierarchy();
            }
            return _divisionsByID;
        }
    }

    private static Division _root;
    public static Division Root
    {
        get
        {
            if (_root == null) {
                LoadAndSetUpDivisionsHierarchy();
            }
            return _root;
        }
    }

    private Division _parentDivision;
    public Division ParentDivision
    {
        get
        {
            if (_parentDivision == null && DivisionID != 0) {
                _parentDivision = DivisionsByID[DivisionID];

            }
            return _parentDivision;
        }
    }

    private List<Division> _subDivisions = new List<Division>();
    public List<Division> SubDivisions
    {
        get { return _subDivisions; }
    }

    private static void LoadAndSetUpDivisionsHierarchyHierarchy()
    {
        // Load the divisions in a non-recursive way using LINQ
        // (details not shown here).
        _divisions = LoadDivisions();

        // Add the divisions in a dictionary by id
        _divisionsByID = new Dictionary<int, Division>(_divisions.Count);
        foreach (Division division in _divisions) {
            _divisionsByID.Add(division.ID, division);
        }

        // Define sub-divisions and root division
        foreach (Division division in _divisions) {
            if (division.DivisionID == 0) {
                _root = division;
            } else if (division.ParentDivision != null) {
                division.ParentDivision.SubDivisions.Add(division);
            }
        }
    }

    private static List<Division> LoadDivisions()
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 感谢您的输入!!!让我调查一下……
  • 懒惰有利于无限递归。
  • 我添加了一个静态的Root 属性并且代码定义了它的值。 Root 是层次结构的入口点。
  • 我通过添加细分完成了层次结构。现在,各部门自行构建层次结构,不需要为层次结构提供单独的数据结构。层次结构是通过静态Root 属性访问的。此外,您可以访问作为静态属性给出的列表 (Divisions) 和分区字典 (DivisionsByID)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多