C# 表达式树 AndAlso 用于实体框架查询

Car*_*s28 6 c# expression-trees entity-framework-core

尝试将两个表达式与 组合时出现错误AndAlso

步骤 1:使用表达式树构建 EF 对象的表达式:

public override Expression<Func<T, bool>> ToExpression()
{
    var expressionParameter = Expression.Parameter(typeof(T), "p");
    var expressionField = Expression.PropertyOrField(expressionParameter, field);
    var expressionConstraint = Expression.Constant(value);

    BinaryExpression expression = Expression.Equal(expressionField, expressionConstraint);

    return Expression.Lambda<Func<T, bool>>(expression, expressionParameter);
}
Run Code Online (Sandbox Code Playgroud)

如果我.ToExpression();为一个表达式调用并运行此代码,则此代码可以与 EF 正常配合,它会生成表达式:

{ p => (p.MyField1 == "X") }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试做的时候

步骤 2:将两个表达式组合为AndAlso

public override Expression<Func<T, bool>> ToExpression()
{
    Expression<Func<T, bool>> leftExpression = left.ToExpression();
    Expression<Func<T, bool>> rightExpression = right.ToExpression();

    BinaryExpression andExpression = Expression.AndAlso(leftExpression.Body, rightExpression.Body);

    return Expression.Lambda<Func<T, bool>>(andExpression, leftExpression.Parameters.Single());
}
Run Code Online (Sandbox Code Playgroud)

这会产生一个表达式:

{ p => ((p.MyField1 == "X") AndAlso (p.MyField2 == "Y")) }
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很好,但是当尝试使用它调用它时,.Where(expression)我收到此错误:

System.InvalidOperationException:无法翻译 LINQ 表达式“p”。以可翻译的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端计算

知道为什么单独的表达式有效但组合在一起却AndAlso无效吗?

Car*_*s28 0

实现ParameterReplacer达到了目的,我发现并使用了实现:

    internal class ReplaceExpressionVisitor : ExpressionVisitor
{
    private readonly Expression _oldValue;
    private readonly Expression _newValue;

    public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
    {
        _oldValue = oldValue;
        _newValue = newValue;
    }

    public override Expression Visit(Expression node) => node == _oldValue ? _newValue : base.Visit(node);
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的建议。