Reputation: 11389
I`m using Linq To Entities to power up my app and i want to create quite a complex search query... see what I want is:
Upon a user entering a string like "Washington Boston" i will break it in N strings, according to the amount of " "(empty spaces, in this case 2 strings) and search my Counties table for Washington and for Boston
If this were a "static" query i would write it like this:where county.Name.Contains("Washington") || county.Name.Contains("Boston")
but i don't know how many cities (or white spaces for this matter) the user will enter...
In a classic pure TSQL enviroment i would compile the query on runtime and use the command Exec... so my question here is: How to dynamically generate a LINQ to entities query?
Please take note that .Where() is not a extension method based on delegates... it does not translate to TSQL on the backend, meaning from e in context.Counties.Where(c => c.Name.Contains("boston"))
translates to SELECT ID,NAME FROM COUNTIES
on the backend
Upvotes: 0
Views: 883
Reputation: 28698
I'll just expand David Khaykin's comment into an answer, because it is the simplest way to achieve the requirement.
You simply need to split the search term into a list of terms, and then filter your counties
entity using the Contains
method according to your requirement
var terms = searchTerm.Split(' ').ToList();
// an exact match
counties.Where(c => terms.Contains(c.Name))
// a 'contains' or 'like' type match
counties.Where(c => terms.Any(t => c.Contains(t));
The Contains
method is the System.Linq.Enumerable.Contains, not String.Contains
.
When writing any complex dynamic LINQ queries, you can use the method outlined by bmused - very powerful. But for this type of simple filtering you can pass straight lists.
Upvotes: 4
Reputation: 981
You could use Predicate builder (and LINQKit because you're using Entity Framework), which will let you do this:
IQueryable<County> SearchInCountyNames(params string[] countyNames)
{
var predicate = PredicateBuilder.False<County>();
foreach (string countyName in countyNames)
{
string name = countyName;
predicate = predicate.Or(c => c.Name.Contains(name));
}
return dataContext.Counties.AsExpandable().Where(predicate);
}
There's a bunch more examples on the predicate builder site.
Upvotes: 2
Reputation:
you could use System.Linq.Expressions
So you would do something like (Not tested):
public Expression<Func<County, Boolean>> GetPredicate(List<String> terms)
{
//The string method - Contains
MethodInfo mContains = typeof(String).GetMethod("Contains");
//The parameter - county
ParameterExpression pe = Expression.Parameter(typeof(County), "County");
//The property - Name
Expression property = Expression.Property(pe, "Name");
//expression body
Expression body = null;
foreach(String term in terms)
{
//the constant to look for
Expression searchTerm = Expression.Constant(term);
//build expression body
if(body == null) body = Expression.Call(property, mContains, searchTerm);
else body = Expression.OrElse(body,
Expression.Call(property, mContains, searchTerm));
}
//create predicate
return Expression.Lambda<Func<County, Boolean>>(body, pe);
}
Upvotes: 2