I have two expressions of type Expression<Func<T, bool>> and I want to take to OR, AND or NOT of these and get a new expression of the same type
Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;
...
//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
Well, you can use Expression.AndAlso / OrElse etc to combine logical expressions, but the problem is the parameters; are you working with the same ParameterExpression in expr1 and expr2? If so, it is easier:
var body = Expression.AndAlso(expr1.Body, expr2.Body);
var lambda = Expression.Lambda<Func<T,bool>>(body, expr1.Parameters[0]);
This also works well to negate a single operation:
static Expression<Func<T, bool>> Not<T>(
this Expression<Func<T, bool>> expr)
{
return Expression.Lambda<Func<T, bool>>(
Expression.Not(expr.Body), expr.Parameters[0]);
}
Otherwise, depending on the LINQ provider, you might be able to combine them with Invoke:
// OrElse is very similar...
static Expression<Func<T, bool>> AndAlso<T>(
this Expression<Func<T, bool>> left,
Expression<Func<T, bool>> right)
{
var param = Expression.Parameter(typeof(T), "x");
var body = Expression.AndAlso(
Expression.Invoke(left, param),
Expression.Invoke(right, param)
);
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
return lambda;
}
Somewhere, I have got some code that re-writes an expression-tree replacing nodes to remove the need for Invoke, but it is quite lengthy (and I can't remember where I left it...)
Generalized version that picks the simplest route:
static Expression<Func<T, bool>> AndAlso<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
// need to detect whether they use the same
// parameter instance; if not, they need fixing
ParameterExpression param = expr1.Parameters[0];
if (ReferenceEquals(param, expr2.Parameters[0]))
{
// simple version
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(expr1.Body, expr2.Body), param);
}
// otherwise, keep expr1 "as is" and invoke expr2
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(
expr1.Body,
Expression.Invoke(expr2, param)), param);
}
Starting from .NET 4.0, there is the ExpressionVisitor class which allows you to build expressions that are EF safe.
public static Expression<Func<T, bool>> AndAlso<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var parameter = Expression.Parameter(typeof (T));
var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
var left = leftVisitor.Visit(expr1.Body);
var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
var right = rightVisitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(left, right), parameter);
}
private class ReplaceExpressionVisitor
: ExpressionVisitor
{
private readonly Expression _oldValue;
private readonly Expression _newValue;
public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
{
_oldValue = oldValue;
_newValue = newValue;
}
public override Expression Visit(Expression node)
{
if (node == _oldValue)
return _newValue;
return base.Visit(node);
}
}
You can use Expression.AndAlso / OrElse to combine logical expressions, but you have to make sure the ParameterExpressions are the same.
I was having trouble with EF and the PredicateBuilder so I made my own without resorting to Invoke, that I could use like this:
var filterC = filterA.And(filterb);
Source code for my PredicateBuilder:
public static class PredicateBuilder {
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b) {
ParameterExpression p = a.Parameters[0];
SubstExpressionVisitor visitor = new SubstExpressionVisitor();
visitor.subst[b.Parameters[0]] = p;
Expression body = Expression.AndAlso(a.Body, visitor.Visit(b.Body));
return Expression.Lambda<Func<T, bool>>(body, p);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b) {
ParameterExpression p = a.Parameters[0];
SubstExpressionVisitor visitor = new SubstExpressionVisitor();
visitor.subst[b.Parameters[0]] = p;
Expression body = Expression.OrElse(a.Body, visitor.Visit(b.Body));
return Expression.Lambda<Func<T, bool>>(body, p);
}
}
And the utility class to substitute the parameters in a lambda:
internal class SubstExpressionVisitor : System.Linq.Expressions.ExpressionVisitor {
public Dictionary<Expression, Expression> subst = new Dictionary<Expression, Expression>();
protected override Expression VisitParameter(ParameterExpression node) {
Expression newValue;
if (subst.TryGetValue(node, out newValue)) {
return newValue;
}
return node;
}
}
If you provider does not support Invoke and you need to combine two expression, you can use an ExpressionVisitor to replace the parameter in the second expression by the parameter in the first expression.
class ParameterUpdateVisitor : ExpressionVisitor
{
private ParameterExpression _oldParameter;
private ParameterExpression _newParameter;
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (object.ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
static Expression<Func<T, bool>> UpdateParameter<T>(
Expression<Func<T, bool>> expr,
ParameterExpression newParameter)
{
var visitor = new ParameterUpdateVisitor(expr.Parameters[0], newParameter);
var body = visitor.Visit(expr.Body);
return Expression.Lambda<Func<T, bool>>(body, newParameter);
}
[TestMethod]
public void ExpressionText()
{
string text = "test";
Expression<Func<Coco, bool>> expr1 = p => p.Item1.Contains(text);
Expression<Func<Coco, bool>> expr2 = q => q.Item2.Contains(text);
Expression<Func<Coco, bool>> expr3 = UpdateParameter(expr2, expr1.Parameters[0]);
var expr4 = Expression.Lambda<Func<Recording, bool>>(
Expression.OrElse(expr1.Body, expr3.Body), expr1.Parameters[0]);
var func = expr4.Compile();
Assert.IsTrue(func(new Coco { Item1 = "caca", Item2 = "test pipi" }));
}
Nothing new here but married this answer with this answer and slightly refactored it so that even I understand what's going on:
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
ParameterExpression parameter1 = expr1.Parameters[0];
var visitor = new ReplaceParameterVisitor(expr2.Parameters[0], parameter1);
var body2WithParam1 = visitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, body2WithParam1), parameter1);
}
private class ReplaceParameterVisitor : ExpressionVisitor
{
private ParameterExpression _oldParameter;
private ParameterExpression _newParameter;
public ReplaceParameterVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
}
I combined some beautiful answers here to make it possible to easily support more Expression operators.
This is based on the answer of #Dejan but now it's quite easy to add the OR as well. I chose not to make the Combine function public, but you could do that to be even more flexible.
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> leftExpression,
Expression<Func<T, bool>> rightExpression) =>
Combine(leftExpression, rightExpression, Expression.AndAlso);
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> leftExpression,
Expression<Func<T, bool>> rightExpression) =>
Combine(leftExpression, rightExpression, Expression.Or);
public static Expression<Func<T, bool>> Combine<T>(Expression<Func<T, bool>> leftExpression, Expression<Func<T, bool>> rightExpression, Func<Expression, Expression, BinaryExpression> combineOperator)
{
var leftParameter = leftExpression.Parameters[0];
var rightParameter = rightExpression.Parameters[0];
var visitor = new ReplaceParameterVisitor(rightParameter, leftParameter);
var leftBody = leftExpression.Body;
var rightBody = visitor.Visit(rightExpression.Body);
return Expression.Lambda<Func<T, bool>>(combineOperator(leftBody, rightBody), leftParameter);
}
private class ReplaceParameterVisitor : ExpressionVisitor
{
private readonly ParameterExpression _oldParameter;
private readonly ParameterExpression _newParameter;
public ReplaceParameterVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return ReferenceEquals(node, _oldParameter) ? _newParameter : base.VisitParameter(node);
}
}
}
Usage is not changed and still like this:
Expression<Func<Result, bool>> noFilterExpression = item => filters == null;
Expression<Func<Result, bool>> laptopFilterExpression = item => item.x == ...
Expression<Func<Result, bool>> dateFilterExpression = item => item.y == ...
var combinedFilterExpression = noFilterExpression.Or(laptopFilterExpression.AndAlso(dateFilterExpression));
efQuery.Where(combinedFilterExpression);
(This is an example based on my actual code, but read it as pseudo-code)
I needed to achieve the same results, but using something more generic (as the type was not known). Thanks to marc's answer I finally figured out what I was trying to achieve:
public static LambdaExpression CombineOr(Type sourceType, LambdaExpression exp, LambdaExpression newExp)
{
var parameter = Expression.Parameter(sourceType);
var leftVisitor = new ReplaceExpressionVisitor(exp.Parameters[0], parameter);
var left = leftVisitor.Visit(exp.Body);
var rightVisitor = new ReplaceExpressionVisitor(newExp.Parameters[0], parameter);
var right = rightVisitor.Visit(newExp.Body);
var delegateType = typeof(Func<,>).MakeGenericType(sourceType, typeof(bool));
return Expression.Lambda(delegateType, Expression.Or(left, right), parameter);
}
I suggest one more improvement to PredicateBuilder and ExpressionVisitor solutions. I called it UnifyParametersByName and you can find it in MIT library of mine: LinqExprHelper. It allows for combining arbitary lambda expressions. Usually the questions are asked about predicate expression, but this idea extends to projection expressions as well.
The following code employs a method ExprAdres which creates a complicated parametrized expression, using inline lambda. This complicated expression is coded only once, and then reused, thanks to the LinqExprHelper mini-library.
public IQueryable<UbezpExt> UbezpFull
{
get
{
System.Linq.Expressions.Expression<
Func<UBEZPIECZONY, UBEZP_ADRES, UBEZP_ADRES, UbezpExt>> expr =
(u, parAdrM, parAdrZ) => new UbezpExt
{
Ub = u,
AdrM = parAdrM,
AdrZ = parAdrZ,
};
// From here an expression builder ExprAdres is called.
var expr2 = expr
.ReplacePar("parAdrM", ExprAdres("M").Body)
.ReplacePar("parAdrZ", ExprAdres("Z").Body);
return UBEZPIECZONY.Select((Expression<Func<UBEZPIECZONY, UbezpExt>>)expr2);
}
}
And this is the subexpression building code:
public static Expression<Func<UBEZPIECZONY, UBEZP_ADRES>> ExprAdres(string sTyp)
{
return u => u.UBEZP_ADRES.Where(a => a.TYP_ADRESU == sTyp)
.OrderByDescending(a => a.DATAOD).FirstOrDefault();
}
What I tried to achieve was to perform parametrized queries without need to copy-paste and with ability to use inline lambdas, which are so pretty. Without all these helper-expression stuff, I would be forced to create whole query in one go.
using System;
using System.Linq.Expressions;
namespace Extensions
{
public class Example
{
//How to use it
public static void Main()
{
Expression<Func<string, bool>> expression1 = exp => true;
Expression<Func<string, bool>> expression2 = exp => false;
Expression<Func<string, bool>> expression3 = ExpressionExtensions.AndAlso(expression1, expression2);
Expression<Func<string, bool>> expression4 = ExpressionExtensions.OrElse(expression1, expression2);
Expression<Func<string, bool>> expression = ExpressionExtensions.AndAlso(expression3, expression4);
}
}
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
ParameterExpression parameter1 = expr1.Parameters[0];
var visitor = new ReplaceParameterVisitor(expr2.Parameters[0], parameter1);
var body2WithParam1 = visitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, body2WithParam1), parameter1);
}
public static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
ParameterExpression parameter1 = expr1.Parameters[0];
var visitor = new ReplaceParameterVisitor(expr2.Parameters[0], parameter1);
var body2WithParam1 = visitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, body2WithParam1), parameter1);
}
private class ReplaceParameterVisitor : ExpressionVisitor
{
private readonly ParameterExpression _oldParameter;
private readonly ParameterExpression _newParameter;
public ReplaceParameterVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
}
}
One more solution (with no ExpressionVisitor) via one method and small enum to identity expression operation type
private static Expression<Func<T, bool>> BindExpressions<T>(ExpressionOperationType operationType, Expression<Func<T, bool>>[] expressionPredicates)
{
var filterExpressionPredicate = expressionPredicates.FirstOrDefault() ?? (x => false);
if (expressionPredicates.Length > 1)
for (int i = 1; i < expressionPredicates.Length; i++)
{
var expressionBody = Expression.Invoke(expressionPredicates[i], filterExpressionPredicate?.Parameters);
var handledExpressionUnits = operationType switch
{
ExpressionOperationType.AndAlso => Expression.AndAlso(filterExpressionPredicate.Body, expressionBody),
_ => Expression.OrElse(filterExpressionPredicate.Body, expressionBody),
};
filterExpressionPredicate = Expression.Lambda<Func<T, bool>>(handledExpressionUnits, filterExpressionPredicate.Parameters);
}
return filterExpressionPredicate;
}
enum ExpressionOperationType
{
AndAlso = 0,
OrElse = 1
}
For instance:
We have a model AuditLog
public class AuditLog
{
public Guid Id { get; set; }
public string OldValues { get; set; }
public string NewValues { get; set; }
public DateTime Timestamp { get; set; }
}
And we want to build specific query: search all audit records with key words "oranges", "cars", "birds" within the boundaries of date (Timestamp)
public IQueryable<AuditLog> BuildQuery()
{
var query = _context.AuditLogs.AsNoTracking();
var commonFilterList = new List<Expression<Func<AuditLog, bool>>>();
commonFilterList.Add(x => x.Timestamp >= DateTime.Now);
commonFilterList.Add(x => x.Timestamp <= DateTime.Now.AddDays(1));
//real world such simple filter case I would use way like:
//query = query
// .Where(x => x.Timestamp >= DateTime.Now)
// .Where(x => x.Timestamp <= DateTime.Now.AddDays(1));
//but this point we keep the example
//using AndAlso
query = query.Where(BindExpressions(ExpressionOperationType.AndAlso, commonFilterList.ToArray()));
//at this point we look at more useful example of using BindExpressions implementation via OrElse expression operation type
var specificFilterList = new List<Expression<Func<AuditLog, bool>>>();
var keyWordsToSearch = new List<string>() { "oranges", "cars", "birds" };
foreach (var keyWord in keyWordsToSearch)
{
//real world we would to use EF.Functions.Contains / EF.Functions.FreeText statements <- but it is question another scope
specificFilterList.Add(x => EF.Functions.Like(x.NewValues, $"%{keyWord}%"));
specificFilterList.Add(x => EF.Functions.Like(x.OldValues, $"%{keyWord}%"));
}
//using OrElse
query = query.Where(BindExpressions(ExpressionOperationType.OrElse, specificFilterList.ToArray()));
//as result we get commonFilterList AND specificFilterList
return query;
}
I think this works fine, isn't it ?
Func<T, bool> expr1 = (x => x.Att1 == "a");
Func<T, bool> expr2 = (x => x.Att2 == "b");
Func<T, bool> expr1ANDexpr2 = (x => expr1(x) && expr2(x));
Func<T, bool> expr1ORexpr2 = (x => expr1(x) || expr2(x));
Func<T, bool> NOTexpr1 = (x => !expr1(x));
Having a list of models:
List<string> models = new List<string>
{
"abcd1234",
"xycd9999",
"zzz999z",
"ros7777"
};
Having a filterer list:
List<string> filterer = new List<string>
{
"cd",
"9999"
};
I am trying using LINQ to get all the models that contains as part of their name the filterer items.
For this example:
"abcd1234" and "xycd9999" contains "cd"
"xycd9999" contains "9999"
therefore the LINQ operation will return a list of the two items: "abcd1234" and "xycd9999".
var filteredList = models
.Where(m => m.Contains("/*HERE WILL BE THE FILTERER ITEMS*/"))
.Distinct()
.ToList();
What is the correct syntax?
var filteredList = models
.Where(x => filterer.Any(y => x.Contains(y))
.ToList();
Distinct serves no purpose here, as the Where call doesn't introduce duplicates (unless of course models has duplicate values, and you want to remove those duplicates).
"Or" equivalent in Linq Where() lambda expression
Try to use PredicateBuilder as the link goes:
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 invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
}
In your case:
List<string> models = new List<string>
{
"abcd1234",
"xycd9999",
"zzz999z",
"ros7777"
};
List<string> filterer = new List<string>
{
"cd",
"9999"
};
var predicate = PredicateBuilder.False<string>();
foreach (string filter in filterer)
{
predicate = predicate.Or(f => f.Contains(filter));
}
var filteredList = models.AsQueryable().Where(predicate).ToList();
Using EF 6. Can someone tell me what am I doing wrong?
public List<SearchResult> SearchDocuments(List<SearchCriteria> searchCriterias)
{
List<SearchResult> results = new List<SearchResult>();
var fieldSettings = LoadCoordinateSystemFieldSettings(searchCriterias);
using (var context = CreateContext())
{
var tractsQuery = PredicateBuilder.False<v_UploadByTract_ActiveUploads>();
foreach (var searchCriteria in searchCriterias)
{
var queryBuilder = PredicateBuilder.True<v_UploadByTract_ActiveUploads>();
// tractsQuery
if (searchCriteria.StateAPI.HasValue)
queryBuilder = queryBuilder.And(a => a.StateAPI == searchCriteria.StateAPI.Value);
if (searchCriteria.CountyAPI.HasValue)
queryBuilder = queryBuilder.And(a => a.CountyAPI == searchCriteria.CountyAPI.Value);
// ...
// ... many more similar IF-ANDs
// ...
tractsQuery = tractsQuery.Or(queryBuilder);
}
var searchQuery = context.v_UploadByTract_ActiveUploads.AsExpandable().Where(tractsQuery).ToList();
//.Select(a => SearchResult.Create(a));
//results.AddRange(searchQuery.ToList());
}
return results;
}
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 invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
quetzalcoatl thanks for the answer. The other post did it. From else where I had come across AsExpandable() and overlooked this one thinking it's talking about the same. After reading your post and re-reading the discussion, this worked. Since your post shows up as "comment", I am unable to mark that as the answer.
Any suggestions on how to consolidate those nasty IFs.
C# PredicateBuilder Entities: The parameter 'f' was not bound in the specified LINQ to Entities query expression
For anyone else googling into here, my solution was to Visit a modified expression before returning it into the expression tree. This bound the lambda parameter.
I have the following SQL query -
SELECT * FROM dbo.LocalContacts WHERE name LIKE '%taiwan%' AND name LIKE '%mvp%'
How do I implement it using EF? I need to break down the search string, then do an 'AND' search for each of the keywords. I have the following but this is not what I wanted -
var searchTextLowerCase = Request.QueryString["q"].ToLower().Split(' ');
foreach (var s in searchTextLowerCase)
{
foreach (var x in communities)
{
if (
(!string.IsNullOrWhiteSpace(x.Name) && x.Name.ToLower().Contains(s)) ||
(!string.IsNullOrWhiteSpace(x.Acronym) && x.Acronym.ToLower().Contains(s)) ||
(!string.IsNullOrWhiteSpace(x.OwnerFirstName) && x.OwnerFirstName.ToLower().Contains(s)) ||
(!string.IsNullOrWhiteSpace(x.OwnerEmail) && x.OwnerEmail.ToLower().Contains(s)) ||
(!string.IsNullOrWhiteSpace(x.OwnerLastName) && x.OwnerLastName.ToLower().Contains(s)) ||
)
{
if (!filteredCommunities.Exists(y => y.Id == x.Id))
filteredCommunities.Add(x);
}
}
}
I can construct the SQL query on the fly and execute it against the DB, but can I do it using EF?
This is one way of doing it with PredicateBuilder:
var predicate = PredicateBuilder.False<Community>();
foreach(var s in searchTextLowerCase)
{
predicate = predicate.Or(x => x.Name.ToLower().Contains(s));
predicate = predicate.Or(x => x.Acronym.ToLower().Contains(s))
//.. etc
}
var filteredCommunities = communities.Where(predicate);
The source for PredicateBuilder:
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 invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
}
I didn't test this against a DB, though you should be able to create a Entity Framework model, and then query it. You can add more where conditions, to fullfill all your requirements:
static void Main(string[] args)
{
string holder = "A B C D E";
string[] searchTextLowerCase = holder.ToLower().Split(' ');
using (Model1Container context = new Model1Container())
{
var q = context.Communities;
List<Community> communities = q.Where(c => searchTextLowerCase.Contains(c.Name)).ToList();
}
}
Here's how I got it to work -
IQueryable<Product> SearchProducts (params string[] keywords)
{
IQueryable<Product> query = dataContext.Products;
foreach (string keyword in keywords)
{
string temp = keyword;
query = query.Where (p => p.Description.Contains (temp));
}
return query;
}
Source