This can be done in two stages. The initial parent-child hierarchy (and sorting):
var query = from parent in data where parent.ParentId == null orderby parent.Type join child in data on parent.ID equals child.ParentId into g select new { Parent = parent, Children = g };
The second is a flattering hierarchy
var result = query.Flatten(x => x.Parent, x => x.Children);
For flattering, I used the extension method:
public static IEnumerable<TResult> Flatten<T, TResult>( this IEnumerable<T> sequence, Func<T, TResult> parentSelector, Func<T, IEnumerable<TResult>> childrenSelector) { foreach (var element in sequence) { yield return parentSelector(element); foreach (var child in childrenSelector(element)) yield return child; } }
Sergey Berezovskiy
source share