So I have categories in my database and I've implemented the Nested set model. I'm reading the categories as a flat structure and then I'm turning it into a hierarchy in memory, mapping each entity to a DTO.
Here's my code:
public async Task<IActionResult> GetCategories()
{
var categories = (List<Category>)await _categoryService.GetAllAsync();
var categoryDtos = GetCategoryDtosHierarchy(categories, null);
categoryDtos.RemoveAll(x => x.Depth > 0); // Terrible
return Ok(categoryDtos);
}
private List<CategoryDto> GetCategoryDtosHierarchy(List<Category> categories, Category parent)
{
var categoryDtos = new List<CategoryDto>();
var filteredCategories = categories;
if (parent != null)
{
filteredCategories = categories.Where(x => x.Depth == (parent.Depth + 1) &&
x.Left > parent.Left &&
x.Right < parent.Right).ToList();
}
foreach (Category filteredCategory in filteredCategories)
{
var categoryDto = new CategoryDto
{
Id = filteredCategory.Id,
Name = filteredCategory.Name,
Depth = filteredCategory.Depth,
SubCategories = GetCategoryDtosHierarchy(categories, filteredCategory)
};
categoryDtos.Add(categoryDto);
}
return categoryDtos;
}
So everything works but it feels like somewhat an awkward solution. When the GetCategoryDtosHierarchy(categories, null);
line returns it not only returns the categories with their subcategories but every level below like so:
[
{
"name": "Clothing",
"depth": 0,
"subcategories": [
{
"name": "Men's",
"depth": 1,
"subcategories": [
{
"name": "Suits",
"depth": 2,
"subcategories": []
}
]
},
{
"name": "Women's",
"depth": 1,
"subcategories": []
}
]
},
{
"name": "Men's", // Not supposed to be here
"depth": 1,
"subcategories": [
{
"name": "Suits",
"depth": 2,
"subcategories": []
}
]
},
{
"name": "Women's", // Not supposed to be here
"depth": 1,
"subcategories": []
},
{
"name": "Suits", // Not supposed to be here
"depth": 2,
"subcategories": []
}
]
And it has forced me to run the categoryDtos.RemoveAll(x => x.Depth > 0);
in order to get rid of the excess. I've thought about putting both calls in a new method but I feel like there might be a better solution than this hack.