Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# predicate list passed to Linq Where clause

I have a long Linq Where clause that I would like to populate with a predicate list.

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();

However I'm getting this error:

cannot convert from 'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'

Which is an error on the .where clause. Pulling out the .where compiles just fine.

like image 546
user3754124 Avatar asked Apr 29 '15 20:04

user3754124


2 Answers

I think great answer from Hogan can be simplified and shorten a bit by use of Any and All Linq methods.

To get items that fulfill all the conditions:

var resultAll = listOfItems.Where(p => filters.All(f => f(p)));

And to get the items that fulfill any condition:

var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));
like image 161
PiotrWolkowski Avatar answered Oct 16 '22 12:10

PiotrWolkowski


There are at least two errors in your code:

List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();

change it to

List<Func<Note, bool>> filters = new List<Func<Note, bool>>();

You don't need Expression trees here. You are using IEnumerable<>, not IQueryable<>

notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
  .Where(filters.ToArray()).Take(10).ToList();

There .Where() accepts a single predicate at a time. You could:

notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
  .Where(x => filters.All(x)).Take(10).ToList();

or various other solutions, like:

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();

Because all the .Where() conditions are implicitly in &&.

like image 39
xanatos Avatar answered Oct 16 '22 11:10

xanatos