LINQ classifica uma lista simples baseada em childorder

No momento, estou tentando descobrir uma boa maneira de classificar meus elementos com LINQ e C #, mas não consigo fazer isso.

Para o problema, vamos supor que você tem a seguinte tabela

---TempTable
ID (int)
ParentID (int)
Name (varchar)
SortOrder (int)

O ID e o ParentID estão relacionados entre si e fornecem uma estrutura de dados auto-hierárquica. Os elementos raiz possuem um valor nulo no campo ID. O SortOrder é apenas uma parte da tabela inteira e baseada no ParentID, portanto, os elementos que compartilham o mesmo ParentID têm 1, 2, 3 nele.

Vamos ainda assumir os seguintes dados:

ID = 1
ParentID = null
Name = Test 1
SortOrder = 1

ID = 2
ParentID = 1
Name = Test 2
SortOrder = 1

ID = 3
ParentID = 1
Name = Test 3
SortOrder = 2

ID = 4
ParentID = 2
Name = Test 4
SortOrder = 1

Minha lista plana desejada deve ter a seguinte ordem:

Test 1 //root element with sort order 1 = very top
Test 2 //child element of root with sort order 1
Test 4 //child element of test 2 with sort order 1
Test 3 //child element of root with sort order 2

Também gosto de obter o objeto em si, sem apenas obter uma parte da informação jogou o uso de novos selecionados ...

Esta é uma das minhas tentativas fracassadas:

from x in EntityModel.TempTables //DbSet<TempTable> by EntityFramework - which already holds all elements
   orderby x.SortOrder
   from y in x.TempTableChildren //Navigation Property by EntityFramework
   orderby y.SortOrder
   select y

Agradeço antecipadamente por sua ajuda.

Editar:

A ordem com o ParentID pode ser útil, com o TestData dado desde o ID, os ParentIDs estão em perfeita ordem, mas este não é o caso em um aplicativo real, pois ele pode excluir uma entrada, criar uma nova e colocá-la em um certa ordem sob um pai e você teria algo como:

ID = 193475037
ParentID = 2
Name = Test 192375937
SortOrder = 25

Agora, no aplicativo, seria possível mover este e o ParentID e SortOrder mudariam aleatoriamente para algo como:

ID = 193475037
ParentID = 456798424
Name = Test 192375937
SortOrder = 4

Para explicar melhor o problema aqui está algum código - como eu faria sem uma consulta Linq bonita, mas com 2 e algum retorno de rendimento:

public class LinqTestDemo
{
    Random rand = new Random();
    List<TempTable> list = new List<TempTable>();

    public List<TempTable> GetFlatData()
    {
        list = GetTestData();

        var rootElement = (from x in list
                            where x.ParentID == null
                            orderby x.SortOrder
                            select x).ToList();

        var flatList = OrderChilds(rootElement).ToList();

        foreach (var tempTable in flatList)
        {
            Console.WriteLine(string.Format("ID = {0} - ParentID = {1} - Name = {2} - SortOrder = {3}", tempTable.ID, tempTable.ParentID, tempTable.Name, tempTable.SortOrder));
        }

        return flatList;
    }

    private IEnumerable<TempTable> OrderChilds(List<TempTable> enumerable)
    {
        foreach (var tempTable in enumerable)
        {
            yield return tempTable;

            TempTable table = tempTable;
            var childs = OrderChilds((from x in list
                                        where x.ParentID == table.ID
                                        orderby x.SortOrder
                                        select x).ToList());

            foreach (var child in childs)
            {
                yield return child;
            }
        }
    }

    public List<TempTable> GetTestData()
    {
        var returnValue = new List<TempTable>();
        for (int i = 0; i < 50; i++)
        {
            var tempTable = new TempTable();
            tempTable.ID = i;
            if (i == 0)
                tempTable.ParentID = null;
            else
                tempTable.ParentID = rand.Next(0, i);

            var maxSortOrder = (from x in returnValue
                                where x.ParentID == tempTable.ParentID
                                select (int?)x.SortOrder).Max();

            if (maxSortOrder.HasValue)
                tempTable.SortOrder = maxSortOrder.Value + 1;
            else
                tempTable.SortOrder = 1;

            tempTable.Name = string.Format("Test {0:00}", i);
            returnValue.Add(tempTable);
        }

        return returnValue;
    }

    public class TempTable
    {
        public int ID { get; set; }
        public int? ParentID { get; set; }
        public string Name { get; set; }
        public int SortOrder { get; set; }
    }
}

@ Breadth-First vs Depth-First Traversal: Depois de algumas leituras, eu diria que meu resultado desejado seria Depth-First Traversal, onde os elementos na mesma profundidade de nível devem ser ordenados pela propriedade SortOrder.

questionAnswers(5)

yourAnswerToTheQuestion