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

.Net Core LINQ多条件查询:List<int>为空时如何跳过对应筛选逻辑

电商商品多维度动态筛选实现方案

核心实现逻辑

利用IQueryable的延迟执行特性,逐步拼接过滤条件,仅当参数有效(非空/非空集合/非空白字符串)时才追加对应筛选规则,从根源避免空引用异常,同时消除大量重复代码。

完整重构后代码

public async Task<List<Product>> GetProductAllList(ProductFilterQuery productFilterQuery)
{
    // 1. 定义基础查询:所有场景通用的基础过滤规则
    var baseQuery = DBContext.Products
        .Where(x => !x.IsDeleted 
                  && x.CompanyID != 0 
                  && x.FileRepos.Count != 0 
                  && x.Company.CompanyIsInShopping 
                  && x.ProductIsActive);

    // 2. 动态追加筛选条件:仅参数有效时才拼接对应规则
    if (productFilterQuery.IsFiltered)
    {
        // 处理集合类ID筛选
        if (productFilterQuery.CategoryIDCollection?.Any() == true)
            baseQuery = baseQuery.Where(x => productFilterQuery.CategoryIDCollection.Contains(x.CategoryID));
        
        if (productFilterQuery.SubCategoryIDCollection?.Any() == true)
            baseQuery = baseQuery.Where(x => productFilterQuery.SubCategoryIDCollection.Contains(x.SubCategoryID));
        
        if (productFilterQuery.ChildCategoryIDCollection?.Any() == true)
            baseQuery = baseQuery.Where(x => productFilterQuery.ChildCategoryIDCollection.Contains(x.ChildCategoryID));
        
        if (productFilterQuery.VariantValueIDCollection?.Any() == true)
            baseQuery = baseQuery.Where(x => productFilterQuery.VariantValueIDCollection.Contains(x.VariantValueID));
        
        if (productFilterQuery.CategoryVariantIDCollection?.Any() == true)
            baseQuery = baseQuery.Where(x => productFilterQuery.CategoryVariantIDCollection.Contains(x.CategoryVariantID));

        // 处理价格区间筛选
        if (productFilterQuery.MinValueOfPrice > 0)
            baseQuery = baseQuery.Where(x => x.ProductPrice >= productFilterQuery.MinValueOfPrice);
        if (productFilterQuery.MaxValueOfPrice > productFilterQuery.MinValueOfPrice)
            baseQuery = baseQuery.Where(x => x.ProductPrice <= productFilterQuery.MaxValueOfPrice);

        // 处理字符串类型筛选
        if (!string.IsNullOrWhiteSpace(productFilterQuery.SearchValue))
            baseQuery = baseQuery.Where(x => x.ProductName.Contains(productFilterQuery.SearchValue));
        
        if (!string.IsNullOrWhiteSpace(productFilterQuery.VendorValue))
            baseQuery = baseQuery.Where(x => x.ProductVendor.Equals(productFilterQuery.VendorValue));
        
        if (!string.IsNullOrWhiteSpace(productFilterQuery.TagValue))
            baseQuery = baseQuery.Where(x => x.ProductTag.Contains(productFilterQuery.TagValue));
    }

    // 3. 统一计算分页参数
    const int pageSize = 12;
    int totalCount = await baseQuery.CountAsync();
    int skipCount = pageSize * (productFilterQuery.IndexValue - 1);
    int takeCount = pageSize;
    int remainingCount = totalCount - (productFilterQuery.IndexValue * pageSize);
    if (remainingCount > 0 && remainingCount < pageSize)
    {
        takeCount = pageSize + remainingCount;
    }

    // 4. 统一执行映射、排序、分页查询
    return await baseQuery
        .Select(x => new Product
        {
            ProductID = x.ProductID,
            DataGuidID = x.DataGuidID,
            ProductName = x.ProductName,
            ProductVendor = x.ProductVendor,
            ProductSecondPhotoID = x.ProductSecondPhotoID,
            ProductPrice = x.ProductPrice,
            FileRepos = x.FileRepos.Select(f => new FileRepo
            {
                FileData = f.FileData,
                FileID = f.FileID,
                FilePhotoIsDefault = f.FilePhotoIsDefault,
            }).Where(a => a.FilePhotoIsDefault || a.FileID == x.ProductSecondPhotoID).ToList(),
            CurrencyValue = new CurrencyValue
            {
                CurrencyValueData = x.CurrencyValue.CurrencyValueData,
                Currency = new Currency
                {
                    CurrencySymbol = x.CurrencyValue.Currency.CurrencySymbol
                }
            }
        })
        .OrderBy(x => x.ProductID)
        .Skip(skipCount)
        .Take(takeCount)
        .ToListAsync();
}

方案说明

  • 空引用防护:集合参数使用?.Any() == true判断,参数为null或空集合时自动跳过对应筛选,不会触发空引用异常
  • 无冗余代码:原代码中4份重复的查询、映射逻辑统一抽为公共部分,整体代码量减少70%,后续新增筛选条件仅需追加一行判断即可
  • 兼容性:EF/EF Core可正常识别链式拼接的Where条件,会自动翻译为最优SQL语句,无性能损耗
  • 可扩展性:可将筛选逻辑封装为IQueryable的扩展方法,供其他查询场景复用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:48:01