代码之家  ›  专栏  ›  技术社区  ›  Ali Ersöz

如何用linq获取树型结构的表数据?

  •  1
  • Ali Ersöz  · 技术社区  · 15 年前

    我有一个表,它本身有一个树结构。

    Id ParentId Name
    ----------------
    1    null   x
    2    null   y
    3    null   z
    4    null   t
    5     1     xx
    6     1     xy
    7     1     xz
    8     2     yx
    9     2     yy
    10    9     yyx
    11    10    yyxx
    12    11    yyxxx
    

    我想检索根节点下的整个子树。当我的根节点是“x”时,我想得到节点集{1,5,6,7,10,11,12}。我怎么能靠林肯做到这一点?

    3 回复  |  直到 15 年前
        1
  •  1
  •   Antony Scott    15 年前

    如果您能够更改表结构以添加额外的字段,那么我过去使用的一种方法是使用一个“path”字段,它包含一个用逗号分隔的id列表。

    ID    ParentID    Name      Path
    --    --------    ----      ----
    1     null        x         1
    2     null        y         2
    3     null        z         3
    4     null        t         4
    5     1           xx        1,5
    6     1           xy        1,6
    7     1           xz        1,7
    8     2           yx        2,8
    9     2           yy        2,9
    10    9           yyx       2,9,10
    11    10          yyxx      2,9,10,11
    12    11          yyxxx     2,9,10,11,12
    

    然后可以使用like(或linq中的startswith)基于路径字段进行查询。

    在你的问题中,你说你想得到{1,5,6,7,10,11,12},但是如果我读对了,这些id是两个不同的子树的一部分。

    为了得到“X”和所有的孩子…

    where Path = "1" || Path.StartsWith("1,")
    

    为了得到X的孩子…

    where Path.StartsWith("1,")
    
        2
  •  0
  •   Vladekk    15 年前
        /// <summary>
        /// Allows to recursively select descendants as plain collection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="DescendBy"></param>
        /// <returns></returns>
    
        public static IEnumerable<T> Descendants<T>(
            this IEnumerable<T> source, Func<T, IEnumerable<T>> DescendBy)
        {
            foreach (T value in source)
            {
                yield return value;
    
                foreach (var child in DescendBy(value).Descendants(DescendBy))
                {
                    yield return child;
                }
            }
        }
    

    用途: node.children.descendants(node=>node.children);

        3
  •  0
  •   Vishal Patwardhan    13 年前

    您需要在linq中使用表本身执行内部连接,如下所示:

    from root in TableName 
    join subnodes in TableName on root.Id equals subnodes.ParentId
    select new { Name }
    

    这将检索父ID与ID匹配且表重命名为子节点的所有记录

    谢谢