Вам нужно построить запрос, который ORs результат выражения вашего фильтра для каждого ключевого слова на сущность, что не очень практично, не используя динамический LINQ. Вот метод расширения, который будет делать только, что для вас:
public static class ExtensionMethods
{
public static IQueryable<TEntity> TestPerKey<TEntity, TKey>(
this IQueryable<TEntity> query,
IEnumerable<TKey> keys,
Expression<Func<TEntity, TKey, bool>> testExpression)
{
// create expression parameter
var arg = Expression.Parameter(typeof(TEntity), "entity");
// expression body var
Expression expBody = null;
// for each key, invoke testExpression, logically OR results
foreach(var key in keys)
{
// constant expression for key
var keyExp = Expression.Constant(key);
// testExpression.Invoke expression
var invokeExp = Expression.Invoke(testExpression, arg, keyExp);
if(null == expBody)
{
// first expression
expBody = invokeExp;
}
else
{
// logically OR previous expression with new expression
expBody = Expression.OrElse(expBody, invokeExp);
}
}
// execute Where method w/ created filter expression
return query.Where((Expression<Func<TEntity, bool>>)Expression.Lambda(expBody, arg));
}
}
Использование:
class TestEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
}
static void Main()
{
var testCollection = new TestEntity[]{
new TestEntity(){
Id = 0,
FirstName = "abc",
LastName = "def",
CompanyName = "ghi"
},
new TestEntity(){
Id = 1,
FirstName = "def",
LastName = "ghi",
CompanyName = "jkl"
},
new TestEntity(){
Id = 2,
FirstName = "ghi",
LastName = "jkl",
CompanyName = "mno"
},
new TestEntity(){
Id = 3,
FirstName = "bcd",
LastName = "efg",
CompanyName = "hij"
},
};
var keywords = new[]{
"abc",
"jkl"
};
var query = testCollection.AsQueryable()
.TestPerKey(
keywords,
(t, k) =>
t.FirstName.Contains(k) ||
t.LastName.Contains(k) ||
t.CompanyName.Contains(k));
foreach(var result in query)
{
Console.WriteLine(result.Id);
}
}
Update - попробуйте следующий метод расширения. Это более специфично, но должны работать с EF:
public static IQueryable<TestEntity> TestPerKey(
this IQueryable<TestEntity> query,
IEnumerable<string> keys)
{
MethodInfo containsMethodInfo = typeof(string).GetMethod("Contains");
// create expression parameter
var arg = Expression.Parameter(typeof(TestEntity), "entity");
// expression body var
Expression expBody = null;
// for each key, invoke testExpression, logically OR results
foreach(var key in keys)
{
var expression = Expression.OrElse(
Expression.OrElse(
Expression.Call(Expression.Property(arg, "FirstName"), containsMethodInfo, Expression.Constant(key)),
Expression.Call(Expression.Property(arg, "LastName"), containsMethodInfo, Expression.Constant(key)))
, Expression.Call(Expression.Property(arg, "CompanyName"), containsMethodInfo, Expression.Constant(key)));
if(null == expBody)
{
// first expression
expBody = expression;
}
else
{
// logically OR previous expression with new expression
expBody = Expression.OrElse(expBody, expression);
}
}
// execute Where method w/ created filter expression
return query.Where((Expression<Func<TestEntity, bool>>)Expression.Lambda(expBody, arg));
}
Единственный способ - динамически создавать фильтрацию выражения (в условиях ИЛИ). – Dennis