Предполагая, что вы хотите иметь дело со всем графом иерархических объектов категории одновременно, и предполагая, что вы имеете дело с разумным числом категорий (осознанный акцент), лучше всего загрузить все данные из вашей базы данных SQL за один раз, затем создайте граф дерева объектов в памяти, а не попадите в базу данных для каждого узла в дереве, что может привести к сотням просмотров базы данных.
Например, если было 5 категорий и у каждой было 5 подкатегорий, и у каждой подкатегории было 5 подкатегорий, то вы просматривали 31 попадание в базу данных, чтобы загрузить его с помощью рекурсии из точки базы данных. of-view, даже если вы имеете дело только с 125 фактическими записями базы данных. Выбор всех 125 записей за один раз не приведет к банкротству банка, в котором может быть более 31 попадания в базу данных.
Для этого я бы сначала вернул ваши категории в виде сплющенного списка (псевдокод):
public IList<FlattenedCategory> GetFlattenedCategories()
{
string sql = "SELECT categoryID, categoryName, parentID FROM category";
SqlConnection cn = // open connection dataReader etc. (snip)
while (sdr.Read())
{
FlattenedCategory cat = new FlattenedCategory();
// fill in props, add the 'flattenedCategories' collection (snip)
}
return flattenedCategories;
}
С классом FlateredCategory, блокирующим что-то вроде этого:
public class FlattenedCategory
{
public int CategoryId { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
}
Теперь у нас есть коллекция всех категорий в памяти, мы строим дерево следующим образом:
public IList<Category> GetCategoryTreeFromFlattenedCollection(
IList<FlattenedCategory> flattenedCats, int? parentId)
{
List<Category> cats = new List<Category>();
var filteredFlatCats = flattenedCats.Where(fc => fc.ParentId == parentId);
foreach (FlattenedCategory flattenedCat in filteredFlatCats)
{
Category cat = new Category();
cat.CategoryId = flattenedCat.CategoryId;
cat.Name = flattenedCat.Name;
Ilist<Category> childCats = GetCategoryTreeFromFlattenedCollection(
flattenedCats, flattenedCat.CategoryId);
cat.Children.AddRange(childCats);
foreach (Category childCat in childCats)
{
childCat.Parent = cat;
}
cats.Add(cat);
}
return cats;
}
И назовите это так:
IList<FlattenedCategory> flattenedCats = GetFlattenedCategories();
Ilist<Category> categoryTree = GetCategoryTreeFromFlattenedCollection(flattenedCats, null);
Примечание: в этом примере мы используем Nullable INT для ParentCategoryId, обнуляемое значение будет означать, что это корневая категория (верхнего уровня) (без родителя). Я бы порекомендовал вам сделать поле parentID в вашей базе данных тоже обнуляемым.
Предупреждение: Код не проверен, просто псевдокод, поэтому используйте на свой страх и риск. Это просто для демонстрации общей идеи.