Get All Children to One List - Recursive C#

c# entity-framework linq recursion

Question

C# | .NET 4.5 | Entity Framework 5

I have a class in Entity Framework that looks like this:

public class Location
{
   public long ID {get;set;}
   public long ParentID {get;set;}
   public List<Location> Children {get;set;}
}

ID is the identifier of the location, ParentID links it to a parent, and Children contains all of the children locations of the parent location. I'm looking for some easy way, likely recursively, to get all "Location" and their children to one single List containing the Location.ID's. I'm having trouble conceptualizing this recursively. Any help is appreciated.

This is what I have so far, its an extension to the entity class, but I believe it could be done better/simpler:

public List<Location> GetAllDescendants()
{
    List<Location> returnList = new List<Location>();
    List<Location> result = new List<Location>();
    result.AddRange(GetAllDescendants(this, returnList));
    return result;
}

public List<Location> GetAllDescendants(Location oID, ICollection<Location> list)
{
    list.Add(oID);
    foreach (Location o in oID.Children)
    {
            if (o.ID != oID.ID)
                    GetAllDescendants(o, list);
    }
    return list.ToList();
}

UPDATED

I ended up writing the recursion in SQL, throwing that in a SP, and then pulling that into Entity. Seemed cleaner and easier to me than using Linq, and judging by the comments Linq and Entity don't seem the best route to go. Thanks for all of the help!

1
16
10/8/2013 2:54:43 AM

Accepted Answer

You can do SelectMany

List<Location> result = myLocationList.SelectMany(x => x.Children).ToList();

You can use where condition for some selective results like

List<Location> result = myLocationList.Where(y => y.ParentID == someValue)
                                      .SelectMany(x => x.Children).ToList();

If you only required Id's of Children you can do

List<long> idResult = myLocationList.SelectMany(x => x.Children)
                                    .SelectMany(x => x.ID).ToList();
19
10/8/2013 4:30:54 AM

Popular Answer

Try this Extension method:

public static IEnumerable<T> Flatten<T, R>(this IEnumerable<T> source, Func<T, R> recursion) where R : IEnumerable<T>
{
    return source.SelectMany(x => (recursion(x) != null && recursion(x).Any()) ? recursion(x).Flatten(recursion) : null)
                 .Where(x => x != null);
}

And you can use it like this:

locationList.Flatten(x => x.Children).Select(x => x.ID);


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow