-1

I have a model which consist multi level of sub models. Now I want to filter the data based on most bottom level of child element. Please see the code (it's just for reference)

var treatmentItemss = new List<TreatmentItemViewModel>();

IEnumerable<IPublishedContent> countries = UmbracoContext.Content.GetById(contentId: 1063).Children(); 

foreach (var country in countries)
{
    IEnumerable<IPublishedContent> countys = country.Children();
    foreach (var county in countys)
    {
        IEnumerable<IPublishedContent> cities = county.Children();

        foreach (var city in cities)
        {
            IEnumerable<IPublishedContent> clinics = city.Children();
            foreach (var clinic in clinics)
            {
                IEnumerable<IPublishedContent> clinics2 = clinic.Children();
                foreach (var clinic2 in clinics2)
                {
                    IEnumerable<IPublishedContent> treatmentMenus = clinic2.Children();
                    foreach (var treatmentMenu in treatmentMenus)
                    {
                        IEnumerable<IPublishedContent> treatmentCategories = treatmentMenu.Children();
                        foreach (var treatmentCategory in treatmentCategories)
                        {
                            dynamic treatmentItems = treatmentCategory.Children();
                            foreach (var item in treatmentItems)
                            {
                                treatmentItemss.Add(new TreatmentItemViewModel
                                {
                                    SurgicalProcedure = item.SurgicalProcedure?.Name,
                                    NonSurgicalTreatment = item.NonSurgicalTreatment?.Name,
                                    Title = item.Title,
                                    Id = item.Id,
                                });
                            }
                        }
                    }
                }
            }
        }
    }
}

In above code I want to fetch the data base on SurgicalProcedure.Name for example, I want to get all the data of countries in which SurgicalProcedure.Name == "Angioplasty".

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Okasha Momin
  • 191
  • 3
  • 15
  • 1
    so much complexity for what is essentially a straightforward SQL query – Mitch Wheat Jan 24 '23 at 11:16
  • "Please see the code (it's just for reference)" - it doesn't really explain what challenge you're facing though. It's unclear what you mean by "I want to get all the data of countries in which SurgicalProcedure.Name == "Angioplasty"" - what do you mean by "all data of countries" in this case? Are you just looking for a list of countries which have at least one city with at least one clinic which provides angioplasty? Please clarify your question. – Jon Skeet Jan 24 '23 at 11:18
  • using LINQ `IEnumerable filteredCountries = countries.Where(c => c.Children().Any(co => co.Children().Any(ct => ct.Children().Any(cl => cl.Children().Any(cl2 => cl2.Children().Any(tm => tm.Children().Any(tc => tc.Children().Any(item => item.SurgicalProcedure != null && item.SurgicalProcedure.Name == "Angioplasty")))))))); ` – Vivek Nuna Jan 24 '23 at 11:20
  • @letsdoit, it's very hard to read that code in a comment. You really ought to post a proper answer so that you can format the code. You really ought to post a proper answer regardless. – jmcilhinney Jan 24 '23 at 11:27
  • looks like you can query `treatmentItems` directly since you need `SurgicalProcedure.Name` in which would give you all data that are applied to every single related table (because it's many-to-many relation). Then, use the results to filter the data as needed (like if you need a specific country, just pass the country id with the query ...etc). – iSR5 Jan 24 '23 at 12:31

2 Answers2

0

You could consider writing an iterator method, that does the dirty job of doing the deep dive in the model, and exposes all the TreatmentItemViewModel as an enumerable sequence. Iterators are methods that contain yield return statements:

IEnumerable<TreatmentItemViewModel> GetTreatmentItems(int contentId)
{
    IEnumerable<IPublishedContent> countries = UmbracoContext.Content
        .GetById(contentId).Children(); 

    foreach (var country in countries)
    {
        foreach (var county in country.Children())
        {
            foreach (var city in county.Children())
            {
                foreach (var clinic in city.Children())
                {
                    foreach (var clinic2 in clinic.Children())
                    {
                        foreach (var treatmentMenu in clinic2.Children())
                        {
                            foreach (var treatmentCategory in treatmentMenu.Children())
                            {
                                foreach (var item in treatmentCategory.Children())
                                {
                                    yield return new TreatmentItemViewModel()
                                    {
                                        SurgicalProcedure = item
                                            .SurgicalProcedure?.Name,
                                        NonSurgicalTreatment = item
                                            .NonSurgicalTreatment?.Name,
                                        Title = item.Title,
                                        Id = item.Id,
                                    };
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

You could then query this sequence with the Where LINQ operator:

TreatmentItemViewModel[] results = GetTreatmentItems(contentId: 1063)
    .Where(x => x.SurgicalProcedure == "Angioplasty")
    .ToArray();

Enumerating all these TreatmentItemViewModel entities could result in a lot of garbage, so you could consider defining this type as a struct instead of class.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
0

Having nested code like this is the not good at all. I think you should change your design to support unlimited level of tree grandchildren and ancestors.

To understand the topic checkout this question and answers.

sabsab
  • 1,073
  • 3
  • 16
  • 30