传递给 Linq Where 子句的 C# 谓词列表
C# predicate list passed to Linq Where clause
我有一个很长的 Linq Where
子句,我想用谓词列表填充它。
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
filters.Add(p => p.Title != null && p.Title.ToLower().Contains(searchString));
filters.Add(p => p.Notes != null && p.Notes.ToLower().Contains(searchString));
filters.Add(GlobalSearchUser((List < User > users = new List<User>() { p.user1, p.user2, p.user3, p.user4 }), searchString));
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
但是我收到了这个错误:
cannot convert from 'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'
这是 .where 子句的错误。拉出 .where 编译就好了。
您不能只将谓词数组传递给 where 方法。您需要遍历数组并为数组中的每个表达式继续调用 Where()
,或者找到一种方法将它们全部合并到一个表达式中并使用它。如果你走第二条路线,你会想要使用 LinqKit。
您必须遍历过滤器并 运行 对每个过滤器进行测试。
如果 any 的过滤器为真,您可以像这样使用 linq return true:
.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)})
或者像这样到 return true 如果 all 你的过滤器是 true:
.Where(p => { foreach(f in filters) if (f(p) == false) return(false); return(true)})
您的代码中至少有两个错误:
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
改为
List<Func<Note, bool>> filters = new List<Func<Note, bool>>();
这里不需要 Expression
棵树。您使用的是 IEnumerable<>
,而不是 IQueryable<>
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
.Where()
一次接受一个谓词。你可以:
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(x => filters.All(x)).Take(10).ToList();
或其他各种解决方案,例如:
var notesEnu = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.AsEnumerable();
foreach (var filter in filters)
{
notesEmu = notesEmu.Where(filter);
}
notes = notesEnu.Take(10).ToList();
因为所有.Where()
条件都隐含在&&
中。
我认为可以通过使用 Any
和 All
Linq 方法来简化和缩短 Hogan 的精彩回答。
获取满足所有条件的物品:
var resultAll = listOfItems.Where(p => filters.All(f => f(p)));
并获取满足任何条件的项目:
var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));
我有一个很长的 Linq Where
子句,我想用谓词列表填充它。
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
filters.Add(p => p.Title != null && p.Title.ToLower().Contains(searchString));
filters.Add(p => p.Notes != null && p.Notes.ToLower().Contains(searchString));
filters.Add(GlobalSearchUser((List < User > users = new List<User>() { p.user1, p.user2, p.user3, p.user4 }), searchString));
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
但是我收到了这个错误:
cannot convert from
'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'
这是 .where 子句的错误。拉出 .where 编译就好了。
您不能只将谓词数组传递给 where 方法。您需要遍历数组并为数组中的每个表达式继续调用 Where()
,或者找到一种方法将它们全部合并到一个表达式中并使用它。如果你走第二条路线,你会想要使用 LinqKit。
您必须遍历过滤器并 运行 对每个过滤器进行测试。
如果 any 的过滤器为真,您可以像这样使用 linq return true:
.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)})
或者像这样到 return true 如果 all 你的过滤器是 true:
.Where(p => { foreach(f in filters) if (f(p) == false) return(false); return(true)})
您的代码中至少有两个错误:
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
改为
List<Func<Note, bool>> filters = new List<Func<Note, bool>>();
这里不需要 Expression
棵树。您使用的是 IEnumerable<>
,而不是 IQueryable<>
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
.Where()
一次接受一个谓词。你可以:
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(x => filters.All(x)).Take(10).ToList();
或其他各种解决方案,例如:
var notesEnu = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.AsEnumerable();
foreach (var filter in filters)
{
notesEmu = notesEmu.Where(filter);
}
notes = notesEnu.Take(10).ToList();
因为所有.Where()
条件都隐含在&&
中。
我认为可以通过使用 Any
和 All
Linq 方法来简化和缩短 Hogan 的精彩回答。
获取满足所有条件的物品:
var resultAll = listOfItems.Where(p => filters.All(f => f(p)));
并获取满足任何条件的项目:
var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));