2015-04-29 14 views
7

Ho una lunga clausola Linq Where che vorrei compilare con un elenco di predicati.Elenco dei predicati C# passato a Linq Clausola Dove

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

Comunque sto ottenendo questo errore:

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

Che è un errore sulla clausola .dove. Tirando fuori il .where si compila bene.

risposta

3

È necessario eseguire il loop dei filtri ed eseguire un test su ciascuno di essi.

È possibile farlo con LINQ come questo per tornare vero se qualsiasi dei filtri sono vere:

.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)}) 

o come questo per per tornare vero se tutte dei filtri true:

+0

Aggiungere qualcosa circa il fatto che lui sta usando 'List xanatos

+0

@xanatos yeah Ho aggiunto alcuni commenti :) – Hogan

+0

Può essere meglio servito usando '.Aggregate() 'pure – moarboilerplate

0

Non è possibile passare semplicemente una serie di predicati al metodo where. È necessario eseguire iterazioni sulla matrice e continuare a chiamare Where() per ogni espressione nell'array oppure trovare un modo per unirle tutte insieme in un'unica espressione e utilizzarla. Ti consigliamo di usare LinqKit se segui la seconda rotta.

5

Ci sono almeno due errori nel codice:

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

cambiamento a

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

Non è necessario Expression alberi qui. Si utilizza IEnumerable<>, non IQueryable<>

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

Ci .Where() accetta un singolo predicato alla volta. Si potrebbe:

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

o varie altre soluzioni, come:

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

Poiché tutte le condizioni .Where() sono implicitamente in &&.

4

Penso che la grande risposta di Hogan possa essere semplificata e accorciata un po 'usando i metodi Any e All Linq.

per ottenere gli elementi che soddisfano tutte le condizioni:

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

e per ottenere gli elementi che soddisfano qualsiasi condizione:

var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));