EF 要like多個參數
items = items.Where(x => x.DemoA.Contains("Key1")
|| x.DemoB.Contains("Key2")
|| x.DemoA.Contains("Key1")
|| x.DemoB.Contains("Key2")
可以用下列擴充方法
public static IQueryable<T> FilterByItems<T, TItem>(
this IQueryable<T> query,
IEnumerable<TItem> items,
Expression<Func<T, TItem, bool>> filterPattern,
bool isOr)
{
Expression predicate = null;
foreach (var item in items)
{
var itemExpr = Expression.Constant(item);
var itemCondition = ExpressionReplacer.Replace(filterPattern.Body, filterPattern.Parameters[1], itemExpr);
if (predicate == null)
predicate = itemCondition;
else
{
predicate = Expression.MakeBinary(isOr ? ExpressionType.OrElse : ExpressionType.AndAlso, predicate,
itemCondition);
}
}
if(predicate is null)
{
predicate = Expression.Constant(false);
}
var filterLambda = Expression.Lambda<Func<T, bool>>(predicate, filterPattern.Parameters[0]);
return query.Where(filterLambda);
}
public class ExpressionReplacer : ExpressionVisitor
{
readonly IDictionary<Expression, Expression> _replaceMap;
public ExpressionReplacer(IDictionary<Expression, Expression> replaceMap)
{
_replaceMap = replaceMap ?? throw new ArgumentNullException(nameof(replaceMap));
}
public override Expression Visit(Expression exp)
{
if (exp != null && _replaceMap.TryGetValue(exp, out var replacement))
return replacement;
return base.Visit(exp);
}
public static Expression Replace(Expression expr, Expression toReplace, Expression toExpr)
{
return new ExpressionReplacer(new Dictionary<Expression, Expression> { { toReplace, toExpr } }).Visit(expr);
}
public static Expression Replace(Expression expr, IDictionary<Expression, Expression> replaceMap)
{
return new ExpressionReplacer(replaceMap).Visit(expr);
}
public static Expression GetBody(LambdaExpression lambda, params Expression[] toReplace)
{
if (lambda.Parameters.Count != toReplace.Length)
throw new InvalidOperationException();
return new ExpressionReplacer(Enumerable.Range(0, lambda.Parameters.Count)
.ToDictionary(i => (Expression)lambda.Parameters[i], i => toReplace[i])).Visit(lambda.Body);
}
}
使用時
items = items.FilterByItems(KeyWordList,
(x, keyWord) => x.DemoA.Contains(keyWord) || x.DemoB.Contains(keyWord),
true);
Ref
Lambda/Linq with Contains criteria for multiple keywords
如果內容有誤請多鞭策謝謝