2012-02-21 13 views
5

Innanzitutto, devo dire che ho letto diversi post su questo a StackOverflow ma non riesco a ottenere il risultato desiderato.Linq-to-SQL che combina due espressioni <Func <T, bool>> ("clausola where") con e/o

Lasciatemi spiegare il contesto (semplificato): sto utilizzando Linq-to-SQL per interrogare i clienti con visite recenti al negozio e (facoltativamente) ottenere solo quelli con una certa quantità di pagamenti. Supponiamo di avere un modello con classi di clienti, visite e pagamenti.

Quindi, concentrandosi sulla Where espressione, sto cercando questo:

Expression<Func<Entityes.Clients, bool>> filter = null; 

filter = c => 
      c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince)); 


if (minPayment.HasValue && minPayment.Value > 0) 
{ 
    filter.And(
       c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 
} 

Il metodo filter.And è un metodo di estensione, consigliato in questo forum, qui sotto potete vedere la definizione:

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, 
              Expression<Func<T, bool>> expression2) 
{ 
    InvocationExpression invokedExpression = 
     Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>()); 

    return Expression.Lambda<Func<T, bool>> 
     (Expression.And(expression1.Body, invokedExpression), expression1.Parameters); 
} 

Tuttavia, questo non funziona come previsto e i risultati non vengono filtrati in base all'ammontare del pagamento. Non v'è alcun errore con i dati o LINQ to SQL modello perché questo codice funziona bene:

filter = c => 
      c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince))) 
      && c => c.Payments.Sum(p => p.Quantity) > minPayment.Value; 

Tuttavia, non voglio usare l'ultimo codice perché ho alcuni scenari più complessi, in cui ho bisogno di costruisci l'espressione del filtro passo dopo passo con una combinazione 'e/o' di ciascuna parte.

PD: Sono un tipo "ADO.Net DataSets" che cerca di imparare Linq-to-SQL e presto Entity Framework, spero di essere presto utile alla comunità di StackOverflow.

+3

p.s., si dovrebbe usare il metodo 'Expression.AndAlso()' per generare l'espressione AND logica ('&&'). 'Expression.E()' genera l'espressione AND bit a bit ('&'). –

risposta

3

Non si sta assegnando il risultato di And a niente.

suppongo la rispettiva parte del codice va letta come segue:

if (minPayment.HasValue && minPayment.Value > 0) 
{ 
    filter = filter.And(
      c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 
} 

Il fatto è che il vostro (o così come lei ha ricordato) And funzione rendimenti l'espressione contenente la congiunzione di due espressione. Non altera l'oggetto su cui è invocato.

+0

ahi ... grazie! –

+0

@FranCD Prego. A proposito, mi sono preso la libertà di riportare la domanda alla versione originale, in modo che gli altri visitatori vedessero qual era il vero codice originale. Altrimenti, le risposte qui sotto non hanno senso. – Krizz

0

Partenza LinqKit ed è classe PredicateBuilder: http://www.albahari.com/nutshell/predicatebuilder.aspx

+0

L'implementazione E che utilizzo proviene dalla classe PredicateBuilder e non funziona ... Dov'è l'errore? –

+0

@FranCD c'è un errore nel tuo utilizzo, vedi la mia risposta. – Krizz

1

Il problema è questa linea:

filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

Il metodo And restituisce un altro delegato che non avete assegnato a nulla. Prova questo:

filter = filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

Giusto per chiarire, And è un metodo che prende due espressioni e combina la loro logica di creare una nuova espressione. Non cambia l'espressione su cui è eseguito, ma restituisce la nuova espressione come valore di ritorno. Quindi nel tuo codice stai chiamando filter.And(...) ma non stai facendo nulla con il valore di ritorno, quindi filter fa ancora riferimento all'espressione lambda originale.

Problemi correlati