【问题标题】:Creating a dynamic query using IQueryable使用 IQueryable 创建动态查询
【发布时间】:2013-09-16 19:53:36
【问题描述】:

我正在尝试遍历一个字符串数组并动态创建一个IQueryable 查询。它非常简单,但这是我卡住的地方

var query = context.QuestionsMetaDatas.AsQueryable();

var keywords=new List<string>(){ "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"

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

【问题讨论】:

    标签: c# sql linq iqueryable


    【解决方案1】:

    你试过包含其他方式吗?

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

    这就像一个IN 子句

    【讨论】:

    • 我希望生成这样的查询“从 QuestionsMetaDatas 中选择 *,其中 Text Like 'Test1' OR Text Like 'Test2'”。因为我在做一个字符串比较。我想要 OR 运算符而不是 AND
    • 尝试使用LINQkit;您可以构建动态查询表达式。你可以通过 Nuget 包管理器获取它,关注这个link
    【解决方案2】:

    您可以查看predicate builder,或构建自己的表达式(这里是在IQueryable&lt;QuestionsMetadatas&gt; 上使用静态扩展方法的可能解决方案)

    public static IQueryable<QuestionsMetaDatas> FilterText(this IQueryable<QuestionsMetaDatas> queryable, IEnumerable<string> 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<Func<QuestionsMetaDatas, bool>>(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<string>(){ "Test1","Test2" };
    
    query = query.FilterText(keywords);
    

    或更短

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

    【讨论】:

      【解决方案3】:

      我使用了 Raphael 建议的谓词生成器,它只是包含在您的项目中的一个文件,然后您的示例变为:

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

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

      【讨论】:

        猜你喜欢
        • 2011-02-24
        • 2020-11-10
        • 2011-04-12
        • 2017-04-20
        • 1970-01-01
        • 2019-02-09
        • 2015-02-02
        • 2021-09-09
        • 1970-01-01
        相关资源
        最近更新 更多