I have made algorithms to create a list with nested lists in order to then show them in a tree view. From what users told me, my view method is fine, but the way I create the final list is probably not doing so well since it takes 9 seconds for my page to load on a test web deploy environment.
This is what my viewmodel looks like:
public class CategoryModel
{
public long idCategory { get; set; }
public string name { get; set; }
public string path{ get; set; }
public int idParentCategory { get; set; }
public int order { get; set; }
public int depth { get; set; }
// List of child categories that can go deeper.
// In a way childCategories are branches
public List<CategoryModel> childCategories { get; set; }
public int selected { get; set; }
}
So first, I create a list with all categories:
public List<CategoryModel> GetSuperUserCategories()
{
// I use this model for having a final model to pass to the view
List<CategoryModel> catModel = new List<CategoryModel>();
// Here I retrieve the categories in Entity Framework form, but I add it to CategoryModel
// later on so it can be used as a ViewModel, hence avoiding Entities to be
// in my view
List<Web_Categories> categories = menuRepo.GetAllCategories();
if (categories == null || categories.Count == 0)
return null;
else
{ // Add all categories to the list here
foreach(var cat in categories)
{
//You can see model properties here
catModel.Add(new CategoryModel
{
idCategory = cat.IDCategorie,
name = cat.Nom,
path = cat.CheminPhysique,
idParentCategory = cat.IDCategorieMere,
depth = 0,
order = cat.Ordre,
childCategories = new List<CategoryModel>()
});
}
return catModel;
}
}
Then I have a method to determine the nested lists, which categories has child categories and inside these children categories I do the same:
public List<CategoryModel> getDocumentsChildren(List<CategoryModel> categories)
{
int depth=0;
try
{
long i;
//Loop on categories
foreach (var cat in categories)
{
i = cat.idCategory;
if (cat.idParentCategory == 0) {
cat.depth = 0; //Determine depth for display
continue;
}
//We loop twice to find nested categories
//Is idParentCategory of our current loop equal to our first loop idCategory?
foreach (var nextCat in categories)
{
if (nextCat.idParentCategory == cat.idCategory && nextCat.idCategory != cat.idCategory)
{
nextCat.depth = cat.depth + 1;
cat.childCategories.Add(nextCat);
}
}
}
//Once the children elements have been determined, We can remove top
//nodes so that they don't show and are only nested
foreach (var cat in categories.ToList())
{
if (cat.idParentCategory != 1)
categories.Remove(cat);
}
return categories;
}catch (Exception e)
{
Console.WriteLine("Une erreur s'est produite : " + e.ToString());
return null;
}
}
Finally I sort all the lists with recursive calls:
public List<CategoryModel> SortCategoryModel(List<CategoryModel> model)
{
foreach(var m in model)
{
if (m.childCategories != null)
{
m.childCategories = m.childCategories.OrderBy(c=>c.name).ToList();
//recurse on childCategories
m.childCategories = SortCategoryModel(m.childCategories);
}
}
return model;
}
Note that I have a total of 119 categories. I use these methods for all the treeview generations, also for creating a dynamic menu which takes about 15 seconds to load in test deploy environment. I believe the SortCategoryModel method to be the issue but I'm not sure how to improve it?
I also search childDocuments, but I removed it here because it does not change much
After measuring the time it takes to make these three methods combined, I find 5.4357 milliseconds. It seems weird my page turns to 15 seconds loading. I'll mention my virtual machine is always around 90% RAM usage. Could this be an issue?