Как бы вы прочитали данные SQL, чтобы получить иерархический список единиц?
БЕЗ зависимости от решения только для SQL Server?
public class Unit {
public Unit Parent { get; set; }
public int Id { get; set; }
public String Name { get; set; }
}
List<Unit> list = new List<Unit>();
while(reader.Read())
{
// read sql data into clr object UNIT
}
Таблица имеет 3 столбца:
Id| ParentId | Name
1 | Null | bla
2 | 1 | x
3 | 1 | y
4 | 2 | z
5 | 2 | test
UPDATE
That is the code which is taken from user marc_s:
List<Unit> units = new List<Unit>();
String commandText =
@";WITH Hierarchy AS
(
SELECT
ID, ParentID = CAST(NULL AS INT),
Name, HierLevel = 1
FROM
dbo.Unit
WHERE
ParentID IS NULL
UNION ALL
SELECT
ht.ID, ht.ParentID, ht.Name, h1.HierLevel + 1
FROM
dbo.Unit ht
INNER JOIN
Hierarchy h1 ON ht.ParentID = h1.ID
)
SELECT Id, ParentId, Name
FROM Hierarchy
ORDER BY HierLevel, Id";
using(SqlConnection con = new SqlConnection(_connectionString))
using (SqlCommand cmd = new SqlCommand(commandText, con))
{
con.Open();
// use SqlDataReader to iterate over results
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// get the info from the reader into the "Unit" object
Unit thisUnit = new Unit();
thisUnit.Id = Convert.ToInt32(rdr["Id"]);
thisUnit.UnitName = rdr["Name"].ToString();
// check if we have a parent
if (rdr["ParentId"] != DBNull.Value)
{
// get ParentId
int parentId = Convert.ToInt32(rdr["ParentId"]);
// find parent in list of units already loaded
// NOTE => not needed anymore => Unit parent = units.FirstOrDefault(u => u.Id == parentId);
// Instead use this method to find the parent:
Unit parent = FindParentUnit(units, parentId);
// if parent found - set this unit's parent to that object
if (parent != null)
{
thisUnit.Parent = parent;
parent.Children.Add(thisUnit);
}
}
else
{
units.Add(thisUnit);
}
}
}
}
return units;
Вот скриншот заполненного списка
http://oi41.tinypic.com/rmpe8n.jpg
То есть данные sql из таблицы Unit:
http://oi40.tinypic.com/mt12sh.jpg
Вопрос
На самом деле заполненный список должен иметь только один объект, а не 11 (индекс 0 - 10). Да, первая Единица в Списке заполнена правильно, но Единицы Индекса 1 - 10 не должны быть в списке.
Вот как это должно выглядеть на самом деле:
0
|--1
| |--3
| | |--9
| | |--10
| |--4
|--2
| |--5
| |--6
|--7
|--8
ОБНОВЛЕНИЕ И РЕШЕНИЕ
private static Unit FindParentUnit(List<Unit> units, int parentId)
{
Unit parent;
foreach (Unit u in units)
{
if (u.Id == parentId){
return u;
}
parent = FindParentUnit(u.Children, parentId);
if (parent != null)
return parent;
}
return null;
}