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

そこにサンプル データを配置します。

UserId UserParentId UserName

  • 1 | null | null | ボス
  • 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

このすべての目的は、users テーブルに対する階層クエリを使用して、シャベルのシリアル番号を取得することです。上司はすべてのシャベルを表示しますが、シャベルのみが部下の従業員を管理します。

数千人の従業員と数千人のシャベルが存在する可能性があり、うつ病階層の深さがわからないことを考慮して、LINQ でこれを達成する方法に関するアイデアとヒント。

助けてくれてありがとう。

4

1 に答える 1

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