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

如何在LINQ查询中对ICollection关联字段正确应用Where筛选并控制返回结果

如何在LINQ查询中对ICollection关联字段正确应用Where筛选并控制返回结果

看起来你遇到了两个核心问题:一是怎么正确筛选出包含指定尺寸的产品,二是怎么让返回的ProductSizes集合只保留符合条件的尺寸,而不是把该产品的所有尺寸都带回来对吧?我来一步步帮你梳理清楚。

首先先解释你之前遇到的错误:

你一开始写的Where(p => p.ProductSizes.Where(p => p.Size.Name == "42"))报错,是因为外层Where需要的是一个布尔值(判断这个产品是否符合条件),但内层的Where返回的是一个IEnumerable<ProductSize>集合,类型不匹配,所以编译器报错。你换成Any是对的,Any会返回布尔值——判断这个产品的ProductSizes里有没有符合条件的尺寸,但它的作用只是筛选出符合条件的产品,不会过滤产品自带的ProductSizes集合,所以你才会看到返回的还是所有尺寸。

接下来分两种场景给你解决方案:

场景1:只想筛选出包含尺寸"42"的产品,返回该产品所有尺寸

如果你的需求只是拿到所有有"42"尺寸的产品,不管它还有没有其他尺寸,那你之前的Any写法是正确的,只需要保留这个筛选条件即可:

var result = _tebpooshContext.Products
    .Where(p => p.ProductCategoryId == 1
             && p.ProductTypeId == 2
             && p.ProductSizes.Any(ps => ps.Size.Name == "42")) // 用Any判断产品是否包含目标尺寸
    .Include(p => p.Picture)
    .Include(p => p.ProductSizes)
        .ThenInclude(ps => ps.Size)
    .Select(p => new TileProductDto
    {
        Image = p.Picture?.Url.Replace("SYSTEM_TYPE_SYNCSERVER", "URL"), // 注意加空判断,避免空引用
        Name = p.Name.Trim(),
        Price = p.Price.ToString(),
        ProductSizes = p.ProductSizes.ToList(),
        ProductId = p.Id.ToString(), // 这里你之前拼写错了,应该是ProductId
    })
    .Take(9)
    .ToList();

场景2:筛选出包含尺寸"42"的产品,且返回的ProductSizes只保留"42"

如果你的需求是不仅要筛选出有"42"尺寸的产品,还要让返回的ProductSizes集合里只有"42"这个尺寸,那有两种实现方式:

方式一:在Select投影时过滤关联集合

这种方式兼容性好,适用于所有EF版本:

var result = _tebpooshContext.Products
    .Where(p => p.ProductCategoryId == 1
             && p.ProductTypeId == 2
             && p.ProductSizes.Any(ps => ps.Size.Name == "42")) // 先筛选出符合条件的产品
    .Include(p => p.Picture)
    .Include(p => p.ProductSizes)
        .ThenInclude(ps => ps.Size)
    .Select(p => new TileProductDto
    {
        Image = p.Picture?.Url.Replace("SYSTEM_TYPE_SYNCSERVER", "URL"),
        Name = p.Name.Trim(),
        Price = p.Price.ToString(),
        // 在Select里对ProductSizes进行过滤,只保留尺寸为"42"的项
        ProductSizes = p.ProductSizes.Where(ps => ps.Size.Name == "42").ToList(),
        ProductId = p.Id.ToString(),
    })
    .Take(9)
    .ToList();

方式二:使用Filtered Include(EF Core 5.0+支持)

如果你的项目用的是EF Core 5.0及以上版本,可以用Filtered Include,直接在数据库层面就过滤掉不需要的关联数据,性能更好:

var result = _tebpooshContext.Products
    .Where(p => p.ProductCategoryId == 1
             && p.ProductTypeId == 2
             && p.ProductSizes.Any(ps => ps.Size.Name == "42"))
    .Include(p => p.Picture)
    // 直接在Include的时候就过滤ProductSizes,只加载尺寸为"42"的项
    .Include(p => p.ProductSizes.Where(ps => ps.Size.Name == "42"))
        .ThenInclude(ps => ps.Size)
    .Select(p => new TileProductDto
    {
        Image = p.Picture?.Url.Replace("SYSTEM_TYPE_SYNCSERVER", "URL"),
        Name = p.Name.Trim(),
        Price = p.Price.ToString(),
        // 这里的ProductSizes已经是过滤后的集合了
        ProductSizes = p.ProductSizes.ToList(),
        ProductId = p.Id.ToString(),
    })
    .Take(9)
    .ToList();

最后再提醒几个小细节:

  • 你的Picture是可空类型(public virtual Picture? Picture { get; set; }),所以访问Url的时候一定要加?.空传播运算符,避免空引用异常。
  • 你之前代码里的ProdutId拼写错误,应该改成ProductId,避免后续使用时出问题。

备注:内容来源于stack exchange,提问作者user3671271

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 07:53:10