簡體   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