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

如何在C# Linq查询中使用谓词避免And/Or条件?

如何用谓词重构C# LINQ中的多条件Or判断

绝对可以!你当前的LINQ查询里重复的paraName判断和一堆||条件确实显得冗余,用**谓词表达式(Expression<Func<Booking, bool>>)**完全能重构这段代码,让它更干净、易维护。

核心思路

我们可以把根据paraName选择匹配字段的逻辑抽离成一个单独的方法,这个方法返回对应的谓词表达式,然后直接把这个表达式应用到LINQ查询的Where条件中,彻底消除重复的||判断。

具体实现步骤

1. 编写生成谓词的方法

这个方法根据传入的paraName、intSearch和strSearch,返回对应的查询谓词:

// 假设Comparator是包含搜索字段常量的类,比如Comparator.Bookingid = "bookingid"
private Expression<Func<Booking, bool>> GetSearchPredicate(string paraName, List<int> intSearch, List<string> strSearch)
{
    var lowerPara = paraName.ToLower();
    
    return lowerPara switch
    {
        Comparator.Bookingid => booking => intSearch.Contains(booking.BookingId),
        Comparator.Dccode => booking => strSearch.Contains(booking.DCMaster.DCCode),
        Comparator.Supplierid => booking => intSearch.Contains(booking.SupplierId),
        Comparator.Doorid => booking => intSearch.Contains(booking.DoorId),
        Comparator.Carrierid => booking => intSearch.Contains(booking.CarrierId),
        Comparator.Buyer => booking => strSearch.Contains(booking.Buyer),
        // 处理未匹配的参数,可根据业务需求调整(比如返回true匹配所有,或false不匹配任何)
        _ => booking => false
    };
}

2. 重构原LINQ查询

现在你可以用生成的谓词简化原查询,不管是查询表达式还是链式写法都能适配:

链式写法(更适配表达式树)
// 先获取对应的搜索谓词
var searchPredicate = GetSearchPredicate(paraName, intSearch, strSearch);

var queryableDcbooking = dcBookingEntities.Bookings
    // 连接BookingWorkFlowStatusMasters
    .Join(dcBookingEntities.BookingWorkFlowStatusMasters,
          booking => booking.BookingWorkFlowStatusId,
          status => status.BookingWorkFlowStatusId,
          (booking, _) => booking)
    // 连接StatusMasters
    .Join(dcBookingEntities.StatusMasters,
          booking => booking.StatusId,
          status => status.StatusId,
          (booking, _) => booking)
    // 左连接PNBStatusMasters
    .GroupJoin(dcBookingEntities.PNBStatusMasters,
               booking => booking.PNBStatusId,
               pnbStatus => pnbStatus.PNBStatusId,
               (booking, pnbGroup) => new { booking, pnbGroup })
    .SelectMany(x => x.pnbGroup.DefaultIfEmpty(), (x, _) => x.booking)
    // 应用搜索谓词
    .Where(searchPredicate);
查询表达式写法

如果你更习惯查询表达式,也可以这样写(注意:Compile()会将表达式转为委托,可能导致客户端内存求值,建议优先用链式写法的Where(searchPredicate)):

var searchPredicate = GetSearchPredicate(paraName, intSearch, strSearch);

var queryableDcbooking = from t in dcBookingEntities.Bookings
                        join t1 in dcBookingEntities.BookingWorkFlowStatusMasters 
                            on t.BookingWorkFlowStatusId equals t1.BookingWorkFlowStatusId
                        join t2 in dcBookingEntities.StatusMasters 
                            on t.StatusId equals t2.StatusId
                        join t3 in dcBookingEntities.PNBStatusMasters 
                            on t.PNBStatusId equals t3.PNBStatusId into gj
                        from pnb in gj.DefaultIfEmpty()
                        where searchPredicate.Compile()(t)
                        select t;

这么做的好处

  • 代码更简洁:原查询的Where子句不再堆满重复的条件判断,逻辑一目了然。
  • 易维护:如果以后需要新增搜索字段,只需要在GetSearchPredicate方法里加一个分支即可,不用修改核心查询逻辑。
  • 可读性提升:搜索条件的处理被封装到单独的方法中,核心查询的业务逻辑更清晰。
  • 适配EF解析:返回的Expression<Func<Booking, bool>>是表达式树,EF可以直接将其转换为对应的SQL语句,不会出现客户端内存求值的性能问题。

注意事项

  • 如果intSearch或strSearch是空集合,你可能需要调整默认逻辑(比如返回booking => false避免查询所有数据),具体取决于你的业务需求。
  • 确保Comparator类中的常量与paraName转小写后的字符串匹配,避免大小写不匹配导致的逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:21:14