afr*_*and 4 c# linq expression entity-framework linq-expressions
我有两个表达式在不同的时间构建,但需要合并才能获得where子句的准确"分组".我确实尝试过这个选项,但是我使用的是实体框架而且它不了解这个Invoke功能.我已经看到了一些ExpressionVisitor替代方案,但我不认为我对我需要做的事情有足够的了解.
如果有人能指出我正确的方向,我会非常感激,感觉它就在那里.
条款1A (对象类型Expression<Func<T, bool>>)
{parm => parm.Name.Contains("hat")}
Run Code Online (Sandbox Code Playgroud)
条款1B (对象类型LambdaExpression,但可以使用(Expression<Func<T, bool>>)LambdaExpression)
{parm => parm.Attributes.Any(parm => ((parm.Name == "test") AndAlso (parm.Value == "21")))}
Run Code Online (Sandbox Code Playgroud)
条款需要
{parm =>
parm.Name.Contains("hat") (&&/||)
parm.Attributes.Any(parm => ((parm.Name == "test") AndAlso (parm.Value == "21")))
}
Run Code Online (Sandbox Code Playgroud)
如果有人可以帮我合并第1A条和第1B条,我会非常感谢..
只是一个FYI Where()和Any()子句是从IQueryable获得的泛型方法,不确定是否重要.
Func<MethodInfo, bool> methodLambda = m => m.Name == "Any" && m.GetParameters().Length == 2;
MethodInfo method = typeof(Queryable).GetMethods().Where(methodLambda).Single().MakeGenericMethod(ActualQueryableType);
ParameterExpression parentMember = Expression.Parameter(typeof(T), "parentParm");
// Create Any() Expression tree and convert it to lambda
MethodCallExpression callAny = Expression.Call(method, member, exp);
LambdaExpression lambdaAny = Expression.Lambda(callAny, param);
var combExp = parentExp.And((Expression<Func<T, bool>>)lambdaAny);
MethodCallExpression whereCall = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, new Expression[] {
query.Expression,
Expression.Quote(combExp)
});
query = (IQueryable<T>)query.Provider.CreateQuery(whereCall);
Run Code Online (Sandbox Code Playgroud)
我使用时得到的错误Invoke是:
NotSupportedException异常
LINQ to Entities不支持LINQ表达式节点类型"Invoke".
Ser*_*rvy 11
这是一个PredicateBuilder不使用的实现Invoke:
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}
}
Run Code Online (Sandbox Code Playgroud)
它使用一种Replace方法(下面的实现)将一个表达式的所有实例替换为另一个表达式.
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
Run Code Online (Sandbox Code Playgroud)
使用此功能,您现在可以使用And两个带有相同输入的谓词表达式.