繁体   English   中英

复杂的动态LINQ查询

[英]Complex Dynamic LINQ Query

我正在使用Linq To Entities来启动我的应用程序,我想创建一个非常复杂的搜索查询...看看我想要的是:

用户输入“ Washington Boston”之类的字符串后,我将根据“”的数量将其分解为N个字符串(在此情况下为2个字符串),并在“县”表中搜索“华盛顿”和“波士顿”

如果这是一个“静态”查询,我会这样写: where county.Name.Contains("Washington") || county.Name.Contains("Boston") where county.Name.Contains("Washington") || county.Name.Contains("Boston")但我不知道用户将输入多少个城市(或与此相关的空白区域)...

在经典的纯TSQL环境中,我将在运行时编译查询并使用命令Exec ...,所以这里的问题是:如何动态生成对实体查询的LINQ?

请注意.Where()不是基于委托的扩展方法...它不会转换为后端的TSQL,这意味着from e in context.Counties.Where(c => c.Name.Contains("boston"))转换为后端的SELECT ID,NAME FROM COUNTIES

我只是将David Khaykin的评论扩展成一个答案,因为这是达到要求的最简单方法。

您只需要将搜索词分成词条列表,然后根据需要使用Contains方法过滤您的counties实体

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));

Contains方法是System.Linq.Enumerable.Contains ,而不是String.Contains

编写任何复杂的动态LINQ查询时,可以使用bmused概述的方法-非常强大。 但是对于这种类型的简单过滤,您可以传递直接列表。

您可以使用System.Linq.Expressions

因此,您将执行类似(未测试)的操作:

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);
}

您可以使用“ 谓词”构建器 (和LINQKit,因为您正在使用Entity Framework),这将使您能够执行此操作:

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);
}

谓词构建器站点上还有很多示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM