简体   繁体   English

复杂的动态LINQ查询

[英]Complex Dynamic LINQ Query

I`m using Linq To Entities to power up my app and i want to create quite a complex search query... see what I want is: 我正在使用Linq To Entities来启动我的应用程序,我想创建一个非常复杂的搜索查询...看看我想要的是:

Upon a user entering a string like "Washington Boston" i will break it in N strings, according to the amount of " "(empty spaces, in this case 2 strings) and search my Counties table for Washington and for Boston 用户输入“ Washington Boston”之类的字符串后,我将根据“”的数量将其分解为N个字符串(在此情况下为2个字符串),并在“县”表中搜索“华盛顿”和“波士顿”

If this were a "static" query i would write it like this: where county.Name.Contains("Washington") || county.Name.Contains("Boston") 如果这是一个“静态”查询,我会这样写: where county.Name.Contains("Washington") || county.Name.Contains("Boston") where county.Name.Contains("Washington") || county.Name.Contains("Boston") but i don't know how many cities (or white spaces for this matter) the user will enter... where county.Name.Contains("Washington") || county.Name.Contains("Boston")但我不知道用户将输入多少个城市(或与此相关的空白区域)...

In a classic pure TSQL enviroment i would compile the query on runtime and use the command Exec... so my question here is: How to dynamically generate a LINQ to entities query? 在经典的纯TSQL环境中,我将在运行时编译查询并使用命令Exec ...,所以这里的问题是:如何动态生成对实体查询的LINQ?

Please take note that .Where() is not a extension method based on delegates... it does not translate to TSQL on the backend, meaning from e in context.Counties.Where(c => c.Name.Contains("boston")) translates to SELECT ID,NAME FROM COUNTIES on the backend 请注意.Where()不是基于委托的扩展方法...它不会转换为后端的TSQL,这意味着from e in context.Counties.Where(c => c.Name.Contains("boston"))转换为后端的SELECT ID,NAME FROM COUNTIES

I'll just expand David Khaykin's comment into an answer, because it is the simplest way to achieve the requirement. 我只是将David Khaykin的评论扩展成一个答案,因为这是达到要求的最简单方法。

You simply need to split the search term into a list of terms, and then filter your counties entity using the Contains method according to your requirement 您只需要将搜索词分成词条列表,然后根据需要使用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));

The Contains method is the System.Linq.Enumerable.Contains , not String.Contains . Contains方法是System.Linq.Enumerable.Contains ,而不是String.Contains

When writing any complex dynamic LINQ queries, you can use the method outlined by bmused - very powerful. 编写任何复杂的动态LINQ查询时,可以使用bmused概述的方法-非常强大。 But for this type of simple filtering you can pass straight lists. 但是对于这种类型的简单过滤,您可以传递直接列表。

you could use System.Linq.Expressions 您可以使用System.Linq.Expressions

So you would do something like (Not tested): 因此,您将执行类似(未测试)的操作:

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

You could use Predicate builder (and LINQKit because you're using Entity Framework), which will let you do this: 您可以使用“ 谓词”构建器 (和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);
}

There's a bunch more examples on the predicate builder site. 谓词构建器站点上还有很多示例。

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

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