You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/// <summary>
/// Enables the efficient, dynamic composition of query predicates.
/// </summary>
public static class PredicateBuilder {
/// <summary>
/// Creates a predicate that evaluates to true.
/// </summary>
public static Expression<Func<T, bool>> True<T>() {
return param => true;
}
/// <summary>
/// Creates a predicate that evaluates to false.
/// </summary>
public static Expression<Func<T, bool>> False<T>() {
return param => false;
}
/// <summary>
/// Creates a predicate expression from the specified lambda expression.
/// </summary>
public static Expression<Func<T, bool>> Create<T>(Expression<Func<T, bool>> predicate) {
return predicate;
}
/// <summary>
/// Combines the first predicate with the second using the logical "and".
/// </summary>
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) {
return first.Compose(second, Expression.AndAlso);
}
/// <summary>
/// Combines the first predicate with the second using the logical "or".
/// </summary>
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) {
return first.Compose(second, Expression.OrElse);
}
/// <summary>
/// Negates the predicate.
/// </summary>
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression) {
var negated = Expression.Not(expression.Body);
return Expression.Lambda<Func<T, bool>>(negated, expression.Parameters);
}
/// <summary>
/// Combines the first expression with the second using the specified merge function.
/// </summary>
static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge) {
// zip parameters (map from parameters of second to parameters of first)
var map = first.Parameters
.Select((f, i) => new {f, s = second.Parameters[i]})
.ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with the parameters in the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// create a merged lambda expression with parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
class ParameterRebinder : ExpressionVisitor {
readonly Dictionary<ParameterExpression, ParameterExpression> map;
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);
}
}
}
then if I use the True/False in my query in this way:
query.Where(PredicateBuilder.False().Or())
the query send to the database server (SQL Server) will be some thing like below (parameterized True/False) in its WHERE clause:
WHERE @p0=1 --@p0=0,
OR <other criteria>
similarly, True will be:
WHERE @p0=1 --@p0=1
AND <other cirteria>
but what I prefer are (static Tru/False):
WHERE 0=1 -- don't use a parameter
OR ...
or
WHERE 1=1 --don't use a parameter
AND ...
is that possible and how to achieve that? The reason is that in the real code, I have a chain of criteria in which starts with a True/False predicate, and I found parameterized True/False has very bad performance in some cases vs static True/False.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I have a predicate builder as below:
then if I use the True/False in my query in this way:
query.Where(PredicateBuilder.False().Or())
the query send to the database server (SQL Server) will be some thing like below (parameterized True/False) in its WHERE clause:
similarly, True will be:
but what I prefer are (static Tru/False):
or
is that possible and how to achieve that? The reason is that in the real code, I have a chain of criteria in which starts with a True/False predicate, and I found parameterized True/False has very bad performance in some cases vs static True/False.
Beta Was this translation helpful? Give feedback.
All reactions