C# Linq使用或动态附加Where子句
我一直在尝试使用动态添加的where子句构建linq查询。我有一个网页,其中包含一组复选框,这些复选框被选中以对应于您要搜索的字段: 到目前为止,我掌握的情况如下:C# Linq使用或动态附加Where子句,c#,linq,entity-framework,entity-framework-5,C#,Linq,Entity Framework,Entity Framework 5,我一直在尝试使用动态添加的where子句构建linq查询。我有一个网页,其中包含一组复选框,这些复选框被选中以对应于您要搜索的字段: 到目前为止,我掌握的情况如下: //This calls a select from table to construct the query which the where clauses will be added to IQueryable<AutoCompleteRestultDto> query = GetAutocompleteResul
//This calls a select from table to construct the query which the where clauses will be added to
IQueryable<AutoCompleteRestultDto> query = GetAutocompleteResults();
if (FirstName == true || AllFields == true)
{
Expression<Func<AutoCompleteRestultDto, bool>> firstNameFilter = c => terms.Any(t => c.FirstName.ToLower().Contains(t.ToLower()));
query = query.Where(firstNameFilter);
}
if (LastName == true || AllFields == true)
{
Expression<Func<AutoCompleteRestultDto, bool>> lastNameFilter = c => terms.Any(t => c.LastName.ToLower().Contains(t.ToLower()));
query = query.Where(lastNameFilter);
}
if (KnownAs == true || AllFields == true)
{
Expression<Func<AutoCompleteRestultDto, bool>> knownAsFilter = c => terms.Any(t => c.KnownAs.ToLower().Contains(t.ToLower()));
query = query.Where(knownAsFilter);
}
// etc.
return query
.Select(c => new ContactAutoCompleteModel
{
label = c.FirstName + " " + c.LastName
})
.Take(15)
.OrderBy(d => d.label)
.ToList();
//这将调用select from表来构造将添加where子句的查询
IQueryable query=GetAutocompleteResults();
if(FirstName==true | | AllFields==true)
{
表达式firstNameFilter=c=>terms.Any(t=>c.FirstName.ToLower().Contains(t.ToLower());
query=query.Where(firstNameFilter);
}
if(LastName==true | | AllFields==true)
{
表达式lastNameFilter=c=>terms.Any(t=>c.LastName.ToLower().Contains(t.ToLower());
query=query.Where(lastNameFilter);
}
if(KnownAs==true | | AllFields==true)
{
表达式knownAsFilter=c=>terms.Any(t=>c.KnownAs.ToLower().Contains(t.ToLower());
query=query.Where(knownAsFilter);
}
//等等。
返回查询
.选择(c=>new ContactAutoCompleteModel
{
label=c.FirstName+“”+c.LastName
})
.Take(15)
.OrderBy(d=>d.label)
.ToList();
问题是这个解决方案要求附加的所有表达式同时为真,即:where(第1条、第2条和第3条)
无法确定如何将此更改为或子句,即:where(第1条或第2条或第3条)您正在链接可枚举的
。where
调用您发布的代码。这就是为什么你会得到这样的效果。下面是使用谓词而不是表达式的PredicateBuilder
public static class PredicateExtensions
{
public static Predicate<T> Or<T> (this Predicate<T> p1, Predicate<T> p2)
{
return obj => p1(obj) || p2(obj);
}
public static Predicate<T> And<T> (this Predicate<T> p1, Predicate<T> p2)
{
return obj => p1(obj) && p2(obj);
}
public static Predicate<T> False<T> () { return obj => false; }
public static Predicate<T> True<T> () { return obj => true; }
public static Predicate<T> OrAll<T> (IEnumerable<Predicate<T>> conditions)
{
Predicate<T> result = PredicateExtensions.False<T>();
foreach (Predicate<T> cond in conditions)
result = result.Or<T>(cond);
return result;
}
public static Predicate<T> AndAll<T> (IEnumerable<Predicate<T>> conditions)
{
Predicate<T> result = PredicateExtensions.True<T>();
foreach (Predicate<T> cond in conditions)
result = result.And<T>(cond);
return result;
}
}
公共静态类谓词扩展
{
公共静态谓词Or(此谓词p1,谓词p2)
{
返回obj=>p1(obj)| | p2(obj);
}
公共静态谓词和(此谓词p1,谓词p2)
{
返回obj=>p1(obj)和p2(obj);
}
公共静态谓词False(){return obj=>False;}
公共静态谓词True(){return obj=>True;}
公共静态谓词OrAll(IEnumerable条件)
{
谓词结果=PredicateExtensions.False();
foreach(条件中的谓词cond)
结果=结果或(cond);
返回结果;
}
公共静态谓词AndAll(IEnumerable条件)
{
谓词结果=PredicateExtensions.True();
foreach(条件中的谓词cond)
结果=结果和(cond);
返回结果;
}
}
您可以将上述类似方法用于可枚举项,在某些条件下自定义(apriori)谓词可枚举项:
Predicate<AutoCompleteRestultDto> firstNamePredicate =
c => terms.Any(t => c.FirstName.ToLower().Contains(t.ToLower()));
Predicate<AutoCompleteRestultDto> lastNamePredicate =
c => terms.Any(t => c.LastName.ToLower().Contains(t.ToLower()));
Predicate<AutoCompleteRestultDto> knownAsPredicate =
c => terms.Any(t => c.KnownAs.ToLower().Contains(t.ToLower()));
var all = new Predicate<AutoCompleteRestultDto>[] {
firstNamePredicate,
knownAsPredicate,
lastNamePredicate };
//
var items = query.Where(a => PredicateExtensions.OrAll(all)(a)).ToList();
items = query.Where(a => PredicateExtensions.AndAll(all)(a)).ToList();
谓词firstNamePredicate=
c=>terms.Any(t=>c.FirstName.ToLower().Contains(t.ToLower());
谓词lastNamePredicate=
c=>terms.Any(t=>c.LastName.ToLower().Contains(t.ToLower());
谓词knownAsPredicate=
c=>terms.Any(t=>c.KnownAs.ToLower().Contains(t.ToLower());
var all=新谓词[]{
名字谓词,
知道谓词,
lastNamePredicate};
//
var items=query.Where(a=>predicteextensions.OrAll(all)(a)).ToList();
items=query.Where(a=>PredicateExtensions.AndAll(all)(a)).ToList();
或者像您这样一步一步地迭代添加它们:
Predicate<AutoCompleteRestultDto> orResultPredicate =
PredicateExtensions.False<AutoCompleteRestultDto>();
if (FirstName == true || AllFields == true) {
orResultPredicate=orResultPredicate.Or(firstNamePredicate); }
if (LastName == true || AllFields == true) {
orResultPredicate = orResultPredicate.Or(lastNamePredicate); }
if (KnownAs == true || AllFields == true) {
orResultPredicate = orResultPredicate.Or(knownAsPredicate); }
Func<AutoCompleteRestultDto, bool> funcOr = c => orResultPredicate(c);
//
IQueryable<AutoCompleteRestultDto> query; // initialized already
var items = query.Where(funcOr).ToList();
谓词或ResultPredicate=
PredicateExtensions.False();
if(FirstName==true | | AllFields==true){
orResultPredicate=orResultPredicate.Or(firstNamePredicate);}
如果(LastName==true | | AllFields==true){
orResultPredicate=orResultPredicate.Or(lastNamePredicate);}
如果(KnownAs==true | | AllFields==true){
orResultPredicate=orResultPredicate.Or(knownAsPredicate);}
Func funcOr=c=>orResultPredicate(c);
//
IQueryable查询;//已初始化
var items=query.Where(funcOr.ToList();
您尝试过PredicateBuilder吗?