2011-10-26 12 views
6

Come posso rilevare se a IQueryable<T> è applicato un filtro where?Rileva dove applicato a IQueryable <T>

In questo codice, ho bisogno di sapere di programmazione che queryFiltered ha un where applicata ad esso e non lo fa query

IQueryable<Customer> query = Context.Customers; 
IQueryable<Customer> queryFiltered = Context.Customers 
              .Where(c=>c.Name.Contains("ABC")); 
+1

Perché? dare più contesto potrebbe aiutare a dare una risposta migliore –

risposta

9

Si dovrà analizzare il Expression che viene restituito dalla Expression property sul IQueryable<T> implementazione .

È necessario eseguire una query per chiamare Queryable.Where method mentre si esegue la ricerca per indicizzazione dell'albero Expression.

noti inoltre che mentre Queryable.Where sta per essere il modo più comune per rilevare un filtro where, sintassi di query consente altre implementazioni da utilizzare (a seconda di ciò namespace sono utilizzati nella using directives); se si dispone di qualcosa che non utilizza il metodo di estensione Queryable.Where, sarà necessario cercarlo esplicitamente (o utilizzare un metodo di filtro più generico per un metodo Where che prende un IQueryable<T> e restituisce un IQueryable<T>).

Il ExpressionVisitor class (come pointed out by xanatos) fornisce un modo molto semplice di strisciare dell'albero Expression, Mi consiglia di utilizzare questo approccio come base per l'elaborazione della Expression albero.

Di nota è che le implementazioni di classe ExpressionVisitor sono necessarie per memorizzare ed esporre lo stato a livello di classe. Per questo motivo, sarebbe meglio (IMO) creare classi interne che eseguono l'azione una volta sola e quindi disporre di un metodo pubblico che crei ogni volta una nuova istanza di ExpressionVisitor; questo aiuterà a gestire lo stato di mutamento e, se fatto correttamente, permetterà anche al metodo di essere sicuro per i thread (se questo è un tuo problema).

3

Se si utilizza C# 4.0 è possibile utilizzare questo codice di esempio: Get all 'where' calls using ExpressionVisitor

Si basa su ExpressionVisitor. "Visita" i vari elementi di un IQueryable<T> per trovare le parti Where. Sembra abbastanza semplice.

Se siete su C# = 3.5, è possibile utilizzare il campione ExpressionVisitor da MSDN di How to: Implement an Expression Tree Visitor PLUS il WhereFinder dal link precedente (funzionano correttamente insieme, appena testato)

Per utilizzare il codice:

var wf = new WhereFinder(); 
var wheres = wf.GetWhere(query.Expression); 

if (wheres.Any()) 
{ 
    // There are Where in the query! 
} 

Se sei (correttamente) il più paranoico come Rune FS, al WereFinder.VisitMethodCall, modificare il if a

if (expression.Method.Name == "Where" && expression.Method.DeclaringType.FullName == "System.Linq.Queryable") 
+0

tutto ciò che fondamentalmente fa è cercare un metodo chiamato "dove" che sarebbe facilmente ingannato da un altro metodo non filtrante che viene chiamato dove –

+0

@RuneFS corretto. Ma penso che dovresti postare la correzione al Q/A originale :-) – xanatos

+0

Il post originale si riferisce a uno specifico scenario in cui l'albero delle espressioni è conosciuto in anticipo e un OP vuole estrarre le due clausole where come espressioni. –

1

Il modo più semplice è chiamare q.Expression.ToString().Contains(".Where("). Come puoi vedere, query.Expression.ToString().Contains(".Where(") restituisce false mentre queryFiltered.Expression.ToString().Contains(".Where(") restituisce true.

Potrebbe essere necessaria una maggiore complessità se si contano altre espressioni come "filtro", ma ciò è vero anche con l'espressione approccio visitatore.

C'è qualcosa di piuttosto hacky in merito a questo che ti concedo, ma sembra molto più semplice.

+0

'new int [] {} .AsQueryable(). Select (p =>" .Where ("). ToString(). Contains (". Where (")' :-) – xanatos

+0

@xanatos Ora è solo perverso!) –

+0

@xanatos lo stesso può essere fatto per l'overload di approccio di ExpressionVisitor Dove funziona esattamente come select e sembrerebbe che stiate filtrando dove effettivamente si proietterebbe –

Problemi correlati