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

如何在LINQ多Where子句中复用查询值避免重复查找?

优化LINQ查询:复用重复计算的分类数据

哈哈,这个场景太常见了!你现在的写法确实会让每个Where子句都重复调用GetPropertyValue来提取分类数据,既冗余又影响性能,给你两种实用的优化方案:

方案一:通过Select投影临时对象缓存数据

我们可以先把每个Item和它对应的分类ID集合一次性投影出来,后续的筛选直接复用这个已经计算好的集合:

// 第一步:一次性提取所有需要的数据,缓存分类ID集合
var itemsWithCachedCategories = _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
    .Select(item => new {
        OriginalItem = item,
        CategoryIds = item.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)?
                       .Select(cat => cat.Id) ?? Enumerable.Empty<int>()
    });

// 第二步:用缓存好的分类ID做筛选,避免重复计算
var filteredItems = itemsWithCachedCategories
    .Where(x => level1Category == 0 || x.CategoryIds.Contains(level1Category))
    .Where(x => !level2Categories.Any() || x.CategoryIds.Intersect(level2Categories).Any())
    .Select(x => x.OriginalItem); // 最后还原回原Item对象

为什么这么做?

  • Select只执行一次,每个Item的分类ID集合只会被计算一次,后续的Where都是基于缓存的集合判断
  • 加入了?? Enumerable.Empty<int>()的空值判断,避免当Item没有分类时,GetPropertyValue返回null导致后续调用Contains/Intersect抛出空引用异常

方案二:使用LINQ查询表达式的let关键字

如果你更习惯用LINQ查询表达式语法,let关键字可以帮我们在查询过程中临时存储计算结果,实现同样的缓存效果:

var filteredItems = from item in _umbracoHelper.GetPage(ItemsPage.ModelTypeAlias).Children
                    let categoryIds = item.GetPropertyValue<IEnumerable<IPublishedContent>>(UmbracoAlias.Item.Categories)?
                                      .Select(cat => cat.Id) ?? Enumerable.Empty<int>()
                    where level1Category == 0 || categoryIds.Contains(level1Category)
                    where !level2Categories.Any() || categoryIds.Intersect(level2Categories).Any()
                    select item;

这个方案的优势:

  • 语法更紧凑,逻辑连贯,不需要额外的临时变量存储投影结果
  • let关键字会自动帮我们缓存categoryIds的计算结果,后续的where子句直接复用

两种方案核心思路一致:提前计算并缓存需要重复使用的昂贵数据,避免在多个筛选条件中重复执行属性获取和转换操作,既提升了性能,也让代码更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:21:38