[英]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概述的方法-非常強大。 但是對於這種類型的簡單過濾,您可以傳遞直接列表。
因此,您將執行類似(未測試)的操作:
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.