我的表结构如下所示。
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查询来实现这一点。
答案 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)
我建议最好更改表结构并为模式添加另一个字段
现在,无需递归功能,您就可以通过高性能的打击代码找到更深的层次
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();
}
}