将表达式树作为参数传递给实体数据模型中的另一个表达式树

本文关键字:表达式 数据模型 另一个 实体 参数传递 | 更新日期: 2023-09-27 18:32:17

我有两个表达式树,定义如下:

Expression<Func<string, bool>> BoolExpression { get; }

Expression<Func<Customer, string>> PropertyExpression { get; }

我需要创建一个新的表达式树,该树将产生等效的:

Customer c = null;
var expression = e1(e2(c));

我可以用 Compile(), Invoke() 来做到这一点:

Customers c = null;
var e3 = e1.Compile().Invoke(e2.Compile().Invoke(c));

但是我不能使用编译或调用方法,因为我使用的是EntityDataModel。当我将"表达式"传递给 Where 方法时,它会转换为 SQL 查询并传递给数据库。

PS:我想使用EntityDataModel做某种查询构建器。有 n 场和 m 条件。我想为字段定义 n 个表达式,为条件定义 m 表达式,然后将它们组合在一起。

将表达式树作为参数传递给实体数据模型中的另一个表达式树

选项 1

先试一试 - 我刚刚用 LINQ-to-SQL 尝试过,它可以工作,所以它应该在 EF 中工作。它与你所拥有的没有一百万英里,只是说调用 e1 并调用 e2 的结果:

var e3 = Expression.Lambda<Func<Customer, bool>>(Expression.Invoke(e1, Expression.Invoke(e2, e2.Parameters)), e2.Parameters);

选项 2

我原以为您需要遍历表达式树并替换 BoolExpression func 中 String 参数的用法,如下所示:

// replace parameter use anywhere in e1.Body with e2.Body
var remover = new ParameterReplaceVisitor(e2.Body);
var bb = remover.Visit(e1.Body);
// create a new lambda with our amended body but still with e2 parameters i.e. the Customer
var e3 = Expression.Lambda<Func<Customer, bool>>(bb, e2.Parameters);
public class ParameterReplaceVisitor : ExpressionVisitor
{
    Expression _replace;
    public ParameterReplaceVisitor(Expression replace)
    {
        _replace = replace;
    }
    protected override Expression VisitParameter(ParameterExpression node)
    {
        // when we encounter a parameter replace it
        return _replace;
    }
}

显然,如果您在表达式中引入多个参数,事情会变得更加复杂。