Reputation: 6083
I know there has to be a simple solution.
I have a Category/Subcategory tree. A Category is either a top-level (no Parent Category ID), or a Subcategory (has a Parent Category ID).
My Class:
public class Category
{
public int CategoryId { get; set; }
public int WebsiteId { get; set; }
public Nullable<int> ParentCategoryId { get; set; }
}
My LINQ:
IList<Category> categories = db.Categories
.Where(c => c.WebsiteId == websiteId)
.Include(c => c.SubCategories)
.ToList();
The problem ... if I have the following:
I get Category 1a back in my List of Categories, as well as Category 1's Subcategories.
I'm getting this:
I tried stripping it out with some unholy mess that is 4 recursive methods and 70 lines of Dictionary building and stripping which I can post if anyone wants to see it (it doesn't work)
However, if there is some way to craft the LINQ to get rid of that duplicate, that would be ideal.
Thanks so much in advance!
Upvotes: 0
Views: 62
Reputation: 1618
@David's answer is correct, however it will only work if your category structure is one layer deep.
The code below selects a flat list from the database and converts it into a deep object graph. Note the AsNoTracking()
to prevent any changes from writing back to the database / overhead of manipulating the graph.
Also note that it will be slow for large lists as it is doing a lot of linq lookups etc., and also bringing the entire list of objects down from the database.
var categories = db.Categories.AsNoTracking()
.Where(c => c.WebsiteId == websiteId)
.ToList();
foreach (var category in categories.Where(c => c.ParentCategoryId.HasValue))
{
categories.First(c => c.CategoryId == category.ParentCategoryId.Value).SubCategories.Add(category);
}
categories.RemoveAll(c => c.ParentCategoryId.HasValue);
// categories is now a list of top level categories with deeply-nested sub-categories
Upvotes: 1
Reputation: 219047
If the .Include()
is joining the sub-categories, then you should be able to filter out the sub-categories from the initial list entirely. Which would be anything that has a parent category value. Something like this:
db.Categories
.Where(c => c.WebsiteId == websiteId)
.Where(c => c.ParentCategoryId == null) // filter sub-categories
.Include(c => c.SubCategories)
.ToList();
Upvotes: 1