gpt4 book ai didi

c# - 表达式树和 AND 条件

转载 作者:太空狗 更新时间:2023-10-29 20:13:54 37 4
gpt4 key购买 nike

我正在尝试构建一个过滤器表达式来过滤数据库中的数据。

我编写了以下扩展以根据所选过滤器参数动态构建表达式:

public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> leftExpression,
Expression<Func<T, bool>> rightExpression)
{
var invocationExpression = Expression.Invoke(rightExpression, leftExpression.Parameters.Cast<Expression>());
var andExpression = Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(leftExpression.Body, invocationExpression),
leftExpression.Parameters);

return andExpression;
}

我是这样使用它的:

Expression<Func<MyObject, bool>> expression = x => true;

if(MyFilter.SomeParam) {
expression = expression.And(x=>x.MyProperty == MyFilter.SomeParam);
}

它适用于 NHibernate,但当我将此代码与 Entity Framework 5 一起使用时,它会失败并显示以下异常消息:

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.

有一种解决方法是从数据库中获取整个集合,然后通过 IEnumerable.Where(Func<T1, T2> filterClause) 应用过滤条件。 , 但它不需要所有数据就可以在 Expression<Func<T1, T2>> 时获取一条记录表达式直接转换为 SQL 语句。

是否有任何简单的方法可以使此代码与 Entity Framework 一起工作?

最佳答案

尝试来自 Domain Oriented N-Layered .NET 4.0 Sample App 的这个实现(还有 specification pattern 的实现):

public static class ExpressionBuilder
{
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
}

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.Or);
}

}

public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;

public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}

public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}

protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}

return base.VisitParameter(p);
}

}

关于c# - 表达式树和 AND 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15296696/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com