1

想象一下,当您有一个包含用户的表时,我们的用户具有层次结构。

[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; }

将样本数据放在那里:

用户 ID 用户父 ID 用户名

  • 1 | 空 | 老板
  • 2 | 1 | 戴安娜经理
  • 3 | 2 | 工人山姆
  • 4 | 2 | 工人鲍勃
  • 5 | 1 | 黄经理
  • 6 | 5 | 卢工人

为每个用户分配一把铲子:P

[Key]
public virtual int ShovelId { get; set; }

public virtual string ShovelSerialNumber { get; set; }
public virtual int UserId { get; set; }

将样本数据放在那里:

ShovelId ShovelSerialNumbe UserId

  • 1 | 12345BK | 3
  • 2 | 99999ZK | 4
  • 3 | 88888KP | 6

这一切的目的是获取铲子的序列号,对用户表进行分层查询。老板会看到所有的铲子,但只有铲子管理下属员工。

关于如何在 LINQ 中实现这一点的任何想法和提示,考虑到可能有数千名员工和数千名铁锹,并且不知道凹陷层次结构的深度。

谢谢帮助。

4

1 回答 1

2

第 1 步:使用您的 ORM(例如 linqToSql)加载记录。通过正确的设置,记录之间的所有关系都将自动存在。

Step2:使用普通代码遍历内存树:

    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();
于 2012-11-08T16:37:07.813 回答