您需要构建一个查询,对每个实体的每个关键字的过滤器表达式的结果进行 OR 运算,如果不使用动态 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 );
}
}
更新 - 尝试以下扩展方法。它更具体,但应该与 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 ) );
}