在父子层次结构中查找深度级别

时间:2016-09-30 09:52:57

标签: linq

我的表结构如下所示。

Id  |ParentId|  Name
--- |--------|-------
1   |NULL    |A
2   |1       |B
3   |2       |C
4   |3       |D

A是B的父,B是C的父,C是D的父。

我想计算每个记录的父母怎么样? 例如,B表示A,C表示B,D表示C。

在这种情况下,A的深度级别为0,B为1,C为2,D为3,基于他们拥有的父母数量。

我可以使用递归函数来执行此操作,每次查询记录是否有父项时都要查询。我想以有效的方式使用linq查询来实现这一点。

2 个答案:

答案 0 :(得分:0)

我认为在没有过度计算,多个请求或临时sql表的情况下实现此目的的最佳方法是在Dictionary中同时选择所有表并在C#侧计算父计数。

如果您可以接受,可以使用此功能和添加类来防止过度计算:

public class ParentInfo
{
    public int? ParentId { get; }

    public int? ParentCount { get; set; }

    public ParentInfo(int? parentId)
    {
        ParentId = parentId;
    }
}

private static int GetParentCount(int id, IDictionary<int, ParentInfo> conections)
{
    if (!conections.ContainsKey(id))
        throw new InvalidDataException($"Id = {id} not found in connections");
    var info = conections[id];
    if (info.ParentCount.HasValue) return info.ParentCount.Value;

    var result = 0;
    if (info.ParentId.HasValue) result += 1 + GetParentCount(info.ParentId.Value, conections);
    info.ParentCount = result;
    return result;
}

然后你可以使用这段代码得到结果:

var conections = table.ToDictionary(r => r.Id, r => new ParentInfo(r.ParentId));
var result = conections.Select(c => new
{
    Id = c.Key,
    ParentCount = GetParentCount(c.Key, conections)
}).ToArray();

答案 1 :(得分:0)

我建议最好更改表结构并为模式添加另一个字段 Database ER

现在,无需递归功能,您就可以通过高性能的打击代码找到更深的层次

using (var context = new Entities())
            {
                var foundNode = context.Trees.FirstOrDefault(w => w.Id == 1);
                if (foundNode != null)
                {
                    var deepNode = context.Trees.Where(w => w.Id != foundNode.Id && w.Pattern.StartsWith(foundNode.Pattern)).Select(s => new { s.Pattern.Length, s })
                        .GroupBy(g => g.Length).OrderByDescending(o => o.Key).Select(s => s.Select(sm => sm.s)).FirstOrDefault();
                }
            }