1 回答
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 将它们作为单个表达式正确计算。
- 1 回答
- 0 关注
- 69 浏览
添加回答
举报