为了账号安全,请及时绑定邮箱和手机立即绑定

如何将列表中的字段的值与 Where 子句中另一个列表中的另一个值进行比较

如何将列表中的字段的值与 Where 子句中另一个列表中的另一个值进行比较

C#
四季花海 2022-09-04 16:50:24
我有一个员工评估表的列表,这个表有字段,这个字段中的值在1到10之间。另一个表“结果细分”具有以下列:TotalResultId int, Max double, Min double, Desc string假设我有这个员工评估数据:EmpId  EmpName   TotalResult---  -------   -----------1      Jaims     1.52      Johny     8.33      Moon      5.64      Michle    75      Mariam    96      Kamel     4结果细分值Id   Max    Min   Desc---  ---    ---   -----1     3      1     ~ 30%2     4      3     40%3     5      4     50%4     6      5     60%5     7      6     70%6     10     7     ~ 80%现在,用户拥有“速率细分”表的多选列表如果用户选择 70% 和 40%,则查询应显示以下员工评估:EmpId  EmpName   TotalResult-----  -------   -----------3      Moon      5.66      Kamel     44      Michle    7我写了这个代码if (rateSegIds != null){    var rateSegs = _repositoryRateSeg.Query(x => rateSegId.Contains(x.Id)).ToList();    if (rateSeg.Any())    {        foreach (var segmentation in rateSeg)        {            query = query.Where(x => x.TotalResult > segmentation.Min &&  x.TotalResult <= segmentation.Max);               }    }}rateSegIds是包含用户选择的整数列表rateSegs包含 RateSegmataions 表中根据 Id 列表的记录查询是表的可查询对象EmployeeAppraisal仅当用户从列表中选择一个值时,此代码才有效,如果他/她选择多个值,则查询将不返回任何内容。因为它的行为像“和”,它应该像“OR”一样,但我不知道如何写。
查看完整描述

1 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

这是前一段时间一直困扰我的事情,这个问题只是促使我深入研究了一下。 将附加条件,但如前所述,使用 AndAlso 操作。要使 EF 和 Linq 更动态地支持 OrElse 条件,您需要将表达式树重新构建为一点或将条件重新构建在一起。向 user743382 的异常使用 OrElse 和 AndAlso 表达式方法的答案致敬.Where()

您需要几个类才能使表达式访问者能够将多个表达式的参数排列在一起。像这样:

private Expression<Func<EmployeeAppraisal, bool>> buildFilterExpression(IEnumerable<Segment> segments)

{

    Expression<Func<EmployeeAppraisal, bool>> exp = c => false;


    foreach (var segment in segments)

    {

        Expression<Func<EmployeeAppraisal, bool>> filter = x => x.TotalResult >= segment.Min && x.TotalResult <= segment.Max;

        exp = Expression.Lambda<Func<EmployeeAppraisal, bool>>(Expression.OrElse(exp.Body,

            new ExpressionParameterReplacer(filter.Parameters, exp.Parameters).Visit(filter.Body)), exp.Parameters);

    }


    return exp;

}


private class ExpressionParameterReplacer : ExpressionVisitor

{

    public ExpressionParameterReplacer(IList<ParameterExpression> fromParameters, IList<ParameterExpression> toParameters)

    {

        ParameterReplacements = new Dictionary<ParameterExpression, ParameterExpression>();

        for (int i = 0; i != fromParameters.Count && i != toParameters.Count; i++)

            ParameterReplacements.Add(fromParameters[i], toParameters[i]);

    }


    private IDictionary<ParameterExpression, ParameterExpression> ParameterReplacements

    {

        get;

        set;

    }


    protected override Expression VisitParameter(ParameterExpression node)

    {

        ParameterExpression replacement;

        if (ParameterReplacements.TryGetValue(node, out replacement))

            node = replacement;

        return base.VisitParameter(node);

    }

然后在 EF Linq 表达式中:


var rateSegs = _repositoryRateSeg.Query(x => rateSegId.Contains(x.Id)).ToList();


if (rateSeg.Any())

    query = query.Where(buildFilterExpression(rateSegs));

ExpressionParameterReplacer 和支持类将不同的表达式正文放在一起,并确保它们与同一表达式参数相关联,以便 Linq 将它们作为单个表达式正确计算。


查看完整回答
反对 回复 2022-09-04
  • 1 回答
  • 0 关注
  • 69 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信