想象一下当你有一个包含用户的表的情况时,我们的用户就有了一个层次结构。
[Key]
public virtual int UserId { get; set; }
public virtual UserProfile UserParent { get; set; }
public virtual int? UserParentId { get; set; }
public virtual String UserName { get; set; }
将样本数据放在那里:
UserId UserParentId用户名
为每个用户分配一把铲子:P
[Key]
public virtual int ShovelId { get; set; }
public virtual string ShovelSerialNumber { get; set; }
public virtual int UserId { get; set; }
将样本数据放在那里:
ShovelId ShovelSerialNumbe UserId
所有这一切的目的是获取铲子的序列号,在users表上进行分层查询。老板会看到所有的铲子,但只有铲子管理下属员工。
关于如何在LINQ中实现这一点的任何想法和提示,考虑到可能有数千名员工和数千把铲子,并且不知道萧条等级的深度。
寻求帮助。
答案 0 :(得分:2)
步骤1:使用ORM加载记录(例如,linqToSql)。通过正确的设置,记录之间的所有关系将自动存在。
步骤2:使用普通代码绕过内存中的树:
public static IEnumerable<T> WalkTreeBreadthFirst<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childFunction)
{
// http://en.wikipedia.org/wiki/Breadth-first_search
HashSet<T> seenIt = new HashSet<T>();
Queue<T> toVisit = new Queue<T>();
foreach (T item in source)
{
toVisit.Enqueue(item);
}
while (toVisit.Any())
{
T item = toVisit.Dequeue();
if (!seenIt.Contains(item))
{
seenIt.Add(item);
foreach (T child in childFunction(item))
{
toVisit.Enqueue(child);
}
yield return item;
}
}
}
public static IEnumerable<T> WalkTreeDepthFirst<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> childFunction)
{
// http://en.wikipedia.org/wiki/Depth-first_search
HashSet<T> seenIt = new HashSet<T>();
Stack<T> toVisit = new Stack<T>();
foreach (T item in source.Reverse())
{
toVisit.Push(item);
}
while (toVisit.Any())
{
T item = toVisit.Pop();
if (!seenIt.Contains(item))
{
seenIt.Add(item);
foreach (T child in childFunction(item).Reverse())
{
toVisit.Push(child);
}
yield return item;
}
}
}
例如:
List<Person> bosses = tree.GetBossesByID(3, 4, 5);
List<Shovel> shovels = bosses
.WalkTreeBreadthFirst(x => x.Subordinates)
.Select(p => p.Shovel)
.ToList();