Jason0495
Jason0495

Reputation: 43

How to get a list of parents and children depending on the value of their children in Linq?

I have two models, Category and ExternalResources:

Category

public partial class Category
{
    public long CategoryID { get; set; }
    public string Name { get; set; }
    public Nullable<long> ParentCategoryID { get; set; }

    public virtual ICollection<Category> Subcategories { get; set; }
    public virtual Category ParentCategory { get; set; }
    public virtual ICollection<ExternalResource> ExternalResources { get; set; }
}

ExternalResources

public partial class ExternalResource
{
    public string DisplayText { get; set; }
    public string URL { get; set; }
    public long CategoryID { get; set; }
    public int ExternalResourceID { get; set; }
    public bool SupportItem { get; set; }
    public bool IsInActivity { get; set; }

    public virtual Category Category { get; set; }
}

The variable called IsInActivity is the one I use to know whether to show on the list or not.

I want to show a list with the parents and just their childrens that has the variable IsInActivity set on true

I made a function that returns the parents that contains at least 1 child that has the value in true, but what I want is that it only returns the children that have IsInActivity in true.

public  List<Category> ContainsResources(List<Category> qry)
{
    List<Category> lstResourceIsInActivity =  qry.Where(p => p.ExternalResources.Any(c => c.IsInActivity = true)).ToList();

    return lstResourceIsInActivity;
}

Is there any way to do this with Linq?.

[UPDATED]

Already resolved my previous doubt, another doubt arose, in this case this returns the subcategories but not the parent categories if this has a subcategory(parent) with a selected child.

I made this function but it returns what I mentioned above:

public List<Category> ContainsResources(List<Category> qry)
{
            List<Category> lstResourceIsInActivity = qry.Where(c => c.ExternalResources.Any(r => r.IsInActivity)).Select(c => new Category
            {
                CategoryID = c.CategoryID,
                Name = c.Name,
                ParentCategoryID = c.ParentCategoryID,
                Subcategories = c.Subcategories.Where(b => b.ExternalResources.Any(r => r.IsInActivity) && b.ParentCategoryID != null).Select(b => new Category
                {
                    CategoryID = b.CategoryID,
                    Name = b.Name,
                    ParentCategoryID = b.ParentCategoryID,
                    ExternalResources = b.ExternalResources.Where(r => r.IsInActivity).ToList()
                }).ToList(),
                ParentCategory = c.ParentCategory,
                ExternalResources = c.ExternalResources.Where(r => r.IsInActivity).ToList()
            })
         .ToList();

            return lstResourceIsInActivity;
}

How to solve this with LinQ?

Upvotes: 1

Views: 531

Answers (2)

Anderson Pimentel
Anderson Pimentel

Reputation: 5787

You can try this to reset your ExternalResources collections only to itens where IsInActivity == true:

public List<Category> ContainsResources(List<Category> qry)
{
    List<Category> lstResourceIsInActivity =  qry.Where(p => p.ExternalResources.Any(c => c.IsInActivity)).ToList();

    lstResourceIsInActivity.ForEach(c => c.ExternalResources = c.ExternalResources.Where(e => e.IsInActivity).ToList());

    return lstResourceIsInActivity;
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503779

Assuming you don't want to actually modify the Category objects, you'll need to create new ones with the filtered resources in.

For example:

public List<Category> ContainsResources(List<Category> query) =>
    query.Where(c => c.ExternalResources.Any(r => r.IsInActivity))
         .Select(c => new Category
                 {
                     CategoryID = c.CategoryID,
                     Name = c.Name,
                     ParentCategoryID = c.ParentCategoryID,
                     ExternalResources = c.ExternalResources.Where(r => r.IsInActivity).ToList()
                 })
         .ToList();

Note that I haven't populated ParentCategory or Subcategories here. If you need those, you'll need to do significantly more work to make sure you keep referential integrity etc.

Upvotes: 1

Related Questions