views:

131

answers:

1

I have a method that retrieves a set of records from a database.

I map this data to a business object - let's call the business object ProcessModel. One of the properties in ProcessModel is a list, called ProcessChildren. The property is List.

So, the data is linked by various fields/properties. There is one object at the top of the hierarchical list, then that object has multiple objects in it's ProcessChildren property, those objects have multiple objects in their ProcessChildren properties etc.

Anyway, I wrote quite a bit of code to iterate through the dataset returned, and build the hierarchical list, which I then bind to a TreeView in Silverlight.

I would be very appreciative if someone could provide me with a much cleaner, simpler way to do this, either using linq, or using linq or some other approach via means of an extension method.

I have included the code that I am currently using, to hopefully better illustrate what I am trying to achieve.

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;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
+1  A: 

This related post might help....

Update: here's code in support of comments below... You will need to edit to support your own classes.

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
        }
    }
}
Michael Bray
Thanks - but I'm not sure if that will solve my problem. The reason why is that the person is that post seems to be doing what I have seen a lot of - where there is top level, then a sub-level of items. In my case, it's dynamic, based on each item in the list. One item may have one child, then that child may have three children, then one of those children may have 1 child etc...
Chris
Well I would think you could put something in a loop... like (pseudocode): while(procs.Any(p => p.SubProcs == null) { foreach where proc.SubProcs = null { proc.SubProcs = <parse the raw list to populate a list of subprocs>; } } - that would recursively find all... note that the assigment should return an empty list for leaf processes to avoid an infinite loop.
Michael Bray
BTW, I don't see a 'ParentId' property on Process... where is that? If I can figure that out, then I can post actual working code
Michael Bray
There is a ParentId property. So the way I link the data together is by linking the ParentId and EntityId properties. So, a child's parent would have an EntityId (numeric value) that matches the child's ParentId value.Does that answer your question?
Chris
Oh I see... it must be a custom class, not a standard System.Diagnostics.Process class, which is what I assumed... I'll amend my post with some code that I think would have worked for .NET standard Process class if it had a ParentID... in this case, the main property is just Id.
Michael Bray