Linq建立分层列表

时间:2010-01-07 18:44:43

标签: c# .net linq silverlight

我有一个从数据库中检索一组记录的方法。

我将此数据映射到业务对象 - 让我们调用业务对象ProcessModel。 ProcessModel中的一个属性是一个名为ProcessChildren的列表。该属性为List。

因此,数据通过各种字段/属性进行链接。分层列表顶部有一个对象,然后该对象的ProcessChildren属性中有多个对象,这些对象在其ProcessChildren属性中有多个对象等。

无论如何,我编写了相当多的代码来迭代返回的数据集,然后构建分层列表,然后将其绑定到Silverlight中的TreeView。

如果有人能够使用linq或使用linq或其他方法通过扩展方法为我提供更清洁,更简单的方法,我将非常感激。

我已经包含了我目前使用的代码,希望更好地说明我想要实现的目标。

var processes = new List<Process>();

        var rootLevelProcesses = new List<Process>();

        var allProcesses = new List<Process>();

        foreach (Process process in e.Results)
        {
            process.ProcessChildren = new List<Process>();

            if (process.ParentId > 0 || (process.ParentId == 0 && process.EntityId == 1))
            {
                allProcesses.Add(process);
            }
        }

        var rootProcess =
                    (from parent in e.Results
                     where parent.EntityType == 1 && parent.ContainerLevel <= 1
                     select parent).FirstOrDefault();

        processes.Add(rootProcess);

        var level2Processes = (from parent in allProcesses
                               where parent.EntityType == 1 && parent.ContainerLevel == 2
                               select parent).ToList();

        foreach (Process process in level2Processes)
        {
            var level3Processes = (from parent in allProcesses
                                   where parent.EntityType == 1 && parent.ContainerLevel == 3
                                   select parent).ToList();

            process.ProcessChildren = level3Processes;
        }

        processes[0].ProcessChildren = level2Processes;

        foreach (Process process in processes)
        {
            if (process.ProcessChildren != null && process.ProcessChildren.Count > 0)
            {
                foreach (Process level1 in process.ProcessChildren)
                {
                    if (level1.EntityType == 1)
                    {
                        var children =
                        (from child in allProcesses
                         where child.ParentId == level1.EntityId
                         select child).ToList();

                        level1.ProcessChildren = children;

                        foreach (Process level2 in level1.ProcessChildren)
                        {
                            if (level2.EntityType == 1)
                            {
                                children =
                            (from child in allProcesses
                             where child.ParentId == level2.EntityId
                             select child).ToList();

                                level2.ProcessChildren = children;

                                foreach (Process level3 in level2.ProcessChildren)
                                {
                                    if (level3.EntityType == 1)
                                    {
                                        children =
                                    (from child in allProcesses
                                     where child.ParentId == level3.EntityId
                                     select child).ToList();

                                        level3.ProcessChildren = children;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

2 个答案:

答案 0 :(得分:1)

This related post可能有帮助......

更新:此处的代码支持以下评论...您需要进行编辑以支持自己的课程。

public class Proc
{
    public System.Diagnostics.Process RealProc;
    public List<Proc> SubProcs = null;
}

void Main()
{
    var Processes = from p in System.Diagnostics.Process.GetProcesses() select new Proc { RealProc = p, SubProcs = null };
    while (Processes.Any(pr => pr.SubProcs == null))
    {
        foreach(Proc pr in Processes)
        {
            pr.RealProc.Id.Dump();
            pr.SubProcs = Processes.Where(prx => prx.RealProc.ParentId == pr.Id).ToList();  // doesn't work because no ParentId
        }
    }
}

答案 1 :(得分:1)

我想这个答案有点晚了,但现在就去了。

尝试使用.LookUp(...)扩展方法和递归lambda表达式:

var lookup = e.Results.ToLookup(x => x.ParentId);

Action<IEnumerable<Process>> addChildren = null;
addChildren = ps =>
{
    foreach (var p in ps)
    {
        p.ProcessChildren = lookup[p.EntityId].ToList();
        addChildren(p.ProcessChildren);
    }
};

var rootProcesses = e.Results.Where(x => x.ParentId == 0);

addChildren(rootProcesses);

这对我创建的测试数据很好。我没有使用ContainerLevel属性,因为ParentId关系隐式定义了级别。