You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中基于多层子模型的深层属性过滤优化方案咨询

多层Umbraco内容结构的高效过滤方案

问题背景

现有嵌套层级的Umbraco内容结构(国家→郡→城市→诊所→二级诊所→治疗菜单→治疗分类→治疗项),需要基于最底层TreatmentItem的SurgicalProcedure.Name属性筛选数据(例如筛选出所有关联SurgicalProcedure.Name == "Angioplasty"的国家相关数据)。原代码使用多层嵌套foreach,冗余且低效,需要更优实现方式。

原代码:

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,
                                });
                            }
                        }
                    }
                }
            }
        }
    }
}

优化实现方式

1. 使用Umbraco Descendants 直接定位目标节点

利用Umbraco内置的Descendants方法跳过多层遍历,结合LINQ完成筛选和投影,代码更简洁高效:

var rootNode = UmbracoContext.Content.GetById(1063);
var filteredTreatmentItems = rootNode
    // 指定治疗项的文档类型别名(如"treatmentItem"),缩小遍历范围
    .Descendants("treatmentItem")
    // 筛选符合条件的治疗项
    .Where(item => item.Value<IPublishedContent>("surgicalProcedure")?.Name == "Angioplasty")
    // 投影为目标ViewModel
    .Select(item => new TreatmentItemViewModel
    {
        SurgicalProcedure = item.Value<IPublishedContent>("surgicalProcedure")?.Name,
        NonSurgicalTreatment = item.Value<IPublishedContent>("nonSurgicalTreatment")?.Name,
        Title = item.Value<string>("title"),
        Id = item.Id
    })
    .ToList();

注意:

  • 用强类型Value<T>替代dynamic,避免运行时错误,提升代码可读性。
  • 传入文档类型别名到Descendants,能减少不必要的节点遍历,大幅提升性能。

2. 关联层级数据,获取所属国家信息

如果需要同时获取治疗项及其所属的国家数据,可通过Ancestor方法向上追溯层级:

var rootNode = UmbracoContext.Content.GetById(1063);
var filteredItemsWithCountry = rootNode
    .Descendants("treatmentItem")
    .Where(item => item.Value<IPublishedContent>("surgicalProcedure")?.Name == "Angioplasty")
    .Select(item => new 
    {
        TreatmentItem = new TreatmentItemViewModel
        {
            SurgicalProcedure = item.Value<IPublishedContent>("surgicalProcedure")?.Name,
            NonSurgicalTreatment = item.Value<IPublishedContent>("nonSurgicalTreatment")?.Name,
            Title = item.Value<string>("title"),
            Id = item.Id
        },
        // 向上获取所属国家节点(需指定国家文档类型别名,如"country")
        CountryName = item.Ancestor("country")?.Name,
        CountryId = item.Ancestor("country")?.Id
    })
    .ToList();

3. 自定义递归遍历(适合特殊层级逻辑)

如果需要灵活控制遍历规则,可编写递归方法:

public List<TreatmentItemViewModel> GetFilteredItems(IPublishedContent node, string targetProcedureName)
{
    var result = new List<TreatmentItemViewModel>();
    
    // 判断当前节点是否为治疗项
    if (node.ContentType.Alias == "treatmentItem")
    {
        var procedure = node.Value<IPublishedContent>("surgicalProcedure");
        if (procedure?.Name == targetProcedureName)
        {
            result.Add(new TreatmentItemViewModel
            {
                SurgicalProcedure = procedure.Name,
                NonSurgicalTreatment = node.Value<IPublishedContent>("nonSurgicalTreatment")?.Name,
                Title = node.Value<string>("title"),
                Id = node.Id
            });
        }
        return result;
    }
    
    // 递归遍历子节点
    foreach (var child in node.Children)
    {
        result.AddRange(GetFilteredItems(child, targetProcedureName));
    }
    
    return result;
}

// 调用示例
var rootNode = UmbracoContext.Content.GetById(1063);
var filteredItems = GetFilteredItems(rootNode, "Angioplasty");

性能优化建议

  • 始终在Descendants中指定文档类型别名,减少无效节点遍历。
  • 避免使用dynamic,坚持强类型Value<T>方法,提升代码稳定性与性能。
  • 数据量较大时,缓存筛选结果,减少重复查询开销。

内容的提问来源于stack exchange,提问作者Okasha Momin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:15:31