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

EF Core如何在Where条件中动态切换运算符以避免代码重复?

优化冗余的动态过滤代码

核心思路

重复代码的根源在于相同字段的非空判断逻辑+不同的字符串比较方式,我们可以把比较逻辑抽离成可动态切换的逻辑单元,再用通用方法统一处理每个字段的过滤,彻底消除重复代码。


方案一:适用于内存集合或允许客户端评估的场景

通过委托封装比较逻辑,用通用方法处理单个字段的过滤:

// 1. 根据比较类型获取对应的字符串比较委托
private Func<string, string, bool> GetComparisonLogic(ETipoConfronto tipoConfronto)
{
    return tipoConfronto switch
    {
        ETipoConfronto.Uguale => (fieldVal, inputVal) => fieldVal == inputVal,
        ETipoConfronto.Inizia => (fieldVal, inputVal) => fieldVal.StartsWith(inputVal),
        ETipoConfronto.Contiene => (fieldVal, inputVal) => fieldVal.Contains(inputVal),
        _ => throw new ArgumentOutOfRangeException(nameof(tipoConfronto), "不支持的比较类型")
    };
}

// 2. 通用过滤方法:处理字段非空判断+过滤逻辑
private IQueryable<T> ApplyFieldFilter<T>(IQueryable<T> query, string inputValue, Func<T, string> fieldSelector, Func<string, string, bool> comparison)
{
    if (!string.IsNullOrEmpty(inputValue))
    {
        query = query.Where(item => comparison(fieldSelector(item), inputValue));
    }
    return query;
}

// 3. 简化后的主逻辑
var comparisonLogic = GetComparisonLogic(request.TipoConfronto);
query = ApplyFieldFilter(query, request.Cognome, x => x.Cognome, comparisonLogic);
query = ApplyFieldFilter(query, request.Nome, x => x.Nome, comparisonLogic);
query = ApplyFieldFilter(query, request.CodFisc, x => x.CodFisc, comparisonLogic);

方案二:适用于EF Core等需要数据库端评估的场景

如果是EF Core的IQueryable,直接用委托会触发客户端过滤(性能损耗),需要改用表达式树确保过滤逻辑在数据库执行:

// 1. 根据比较类型获取对应的表达式树
private Expression<Func<string, string, bool>> GetComparisonExpression(ETipoConfronto tipoConfronto)
{
    return tipoConfronto switch
    {
        ETipoConfronto.Uguale => (fieldVal, inputVal) => fieldVal == inputVal,
        ETipoConfronto.Inizia => (fieldVal, inputVal) => fieldVal.StartsWith(inputVal),
        ETipoConfronto.Contiene => (fieldVal, inputVal) => fieldVal.Contains(inputVal),
        _ => throw new ArgumentOutOfRangeException(nameof(tipoConfronto), "不支持的比较类型")
    };
}

// 2. 通用过滤方法:组合表达式树,避免客户端评估
private IQueryable<T> ApplyFieldFilter<T>(IQueryable<T> query, string inputValue, Expression<Func<T, string>> fieldSelector, Expression<Func<string, string, bool>> comparisonExpr)
{
    if (string.IsNullOrEmpty(inputValue))
        return query;

    // 构建表达式:item => comparisonExpr(fieldSelector(item), inputValue)
    var parameter = Expression.Parameter(typeof(T), "item");
    var fieldExpr = Expression.Invoke(fieldSelector, parameter);
    var inputConst = Expression.Constant(inputValue);
    var bodyExpr = Expression.Invoke(comparisonExpr, fieldExpr, inputConst);
    var filterLambda = Expression.Lambda<Func<T, bool>>(bodyExpr, parameter);

    return query.Where(filterLambda);
}

// 3. 简化后的主逻辑
var comparisonExpr = GetComparisonExpression(request.TipoConfronto);
query = ApplyFieldFilter(query, request.Cognome, x => x.Cognome, comparisonExpr);
query = ApplyFieldFilter(query, request.Nome, x => x.Nome, comparisonExpr);
query = ApplyFieldFilter(query, request.CodFisc, x => x.CodFisc, comparisonExpr);

额外优化:批量处理字段

如果后续字段数量增加,可将字段选择器和输入值封装为集合,批量遍历处理:

var filters = new List<(string InputValue, Expression<Func<T, string>> FieldSelector)>
{
    (request.Cognome, x => x.Cognome),
    (request.Nome, x => x.Nome),
    (request.CodFisc, x => x.CodFisc)
};

var comparisonExpr = GetComparisonExpression(request.TipoConfronto);
foreach (var (inputVal, selector) in filters)
{
    query = ApplyFieldFilter(query, inputVal, selector, comparisonExpr);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:09:31