[英]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.