使用IQueryable创建动态查询

我正在尝试迭代字符串数组并动态创建IQueryable查询。 它很简单,但这里是我被困的地方

 var query = context.QuestionsMetaDatas.AsQueryable(); var keywords=new List(){ "Test1","Test2" }; foreach(var key in keywords) { query=query.Where(a=>a.Text.Contains(key)); } 

现在的问题是,当查询生成时,它编译为

 select * from QuestionsMetaDatas where Text Like "Test1" AND Text Like "Test2" 

而不是AND我希望查询生成OR …现在我该如何实现?

我使用了像Raphael建议的谓词构建器,它只是一个文件包含在你的项目中,然后你的例子变成:

 var keywords=new List(){ "Test1","Test2" }; var predicate = PredicateBuilder.False(); foreach (var key in keywords) { predicate = predicate.Or (a => a.Text.Contains (key)); } var query = context.QuestionsMetaDatas.AsQueryable().Where(predicate); 

生成您正在寻找的OR查询。

你尝试过包含其他方式吗?

 var keywords=new List(){ "Test1","Test2" }; query=query.Where(a=>keywords.Contains(a)); 

这就像一个IN子句

您可以查看谓词构建器 ,或构建自己的表达式(这里是一个在IQueryable上使用静态扩展方法的可能解决方案)

 public static IQueryable FilterText(this IQueryable queryable, IEnumerable keywords) { var entityType = typeof(QuestionsMetaDatas); var parameter = Expression.Parameter(entityType, "a"); var containsMethod = typeof(string).GetMethod("Contains" , new[] { typeof(string) }); var propertyExpression = Expression.Property(parameter, "Text"); Expression body = Expression.Constant(false); foreach (var keyword in keywords) { var innerExpression = Expression.Call(propertyExpression, containsMethod, Expression.Constant(keyword)); body = Expression.OrElse(body, innerExpression); } var lambda = Expression.Lambda>(body, new[] { parameter }); return queryable.Where(lambda); } 

lambda将是这样的:

 a => ((False OrElse a.Text.Contains("firstKeyWord")) OrElse a.Text.Contains("secondKeyWord")) 

和用法是

 var query = context.QuestionsMetaDatas.AsQueryable(); var keywords=new List(){ "Test1","Test2" }; query = query.FilterText(keywords); 

或更短

 var query = context.QuestionsMetaDatas.AsQueryable().FilterText(new[]{"Test1", "Test2"});