2011-10-26 15 views
6

¿Cómo puedo detectar si un IQueryable<T> tiene un filtro where aplicado?Detectar dónde se aplica a IQueryable <T>

En este código, necesito saber programación que tiene un queryFilteredwhere que se le aplica y query no lo hace

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

¿Por qué? dar más contexto podría ayudar a dar una mejor respuesta –

Respuesta

9

Usted tendrá que analizar el Expression que se devuelve desde el Expression property sobre la aplicación IQueryable<T> .

Deberá realizar una consulta para llamar al Queryable.Where method mientras rastrea el árbol Expression.

También tenga en cuenta que, si bien Queryable.Where va a ser la forma más común de detectar un filtro where, la sintaxis de consulta permite otras implementaciones que se utilizarán (dependiendo de qué espacios de nombres se utilizan en la using directives); si tiene algo que no está utilizando el método de extensión Queryable.Where, tendrá que buscarlo explícitamente (o utilizar un método más genérico de filtrado para un método Where que toma un IQueryable<T> y devuelve un IQueryable<T>).

El ExpressionVisitor class (como pointed out by xanatos) proporciona una manera muy fácil de rastrear el árbol Expression, recomiendo encarecidamente utilizar este enfoque como base para el procesamiento de su árbol Expression.

Es de destacar que las implementaciones de clase ExpressionVisitor son necesarias para almacenar y exponer el estado en el nivel de clase. Por eso, sería mejor (IMO) crear clases internas que realicen la acción por única vez y luego tener un método público que crea una nueva instancia del ExpressionVisitor todo el tiempo; esto ayudará a lidiar con el estado de mutación y, si se hace correctamente, permitirá que el método también sea seguro para la ejecución de subprocesos (si eso es una preocupación del usuario).

3

Si está usando C# 4.0 se puede utilizar este código de ejemplo: Get all 'where' calls using ExpressionVisitor

Se basa en ExpressionVisitor. "Visita" los diversos elementos de un IQueryable<T> para encontrar las piezas Where. Parece lo suficientemente simple.

Si se encuentra en C# = 3.5, puede utilizar la muestra ExpressionVisitor de MSDN de How to: Implement an Expression Tree Visitor MÁS el WhereFinder desde el enlace anterior (que funcionan correctamente juntos, sólo probado)

Para utilizar el código:

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

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

Si no está (correctamente) tanto paranoica como Rune FS, a la WereFinder.VisitMethodCall, cambiar el if a

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

todo lo que básicamente hace es buscar un método llamado "dónde" que sería engañado fácilmente por otro método no filtrante que se llama donde –

+0

@RuneFS Corregido. Pero sí creo que deberías publicar la corrección en el Q/A original :-) – xanatos

+0

La publicación original se refiere a un escenario específico donde el árbol de expresiones se conoce por adelantado. Un OP quiere extraer las dos cláusulas where como expresiones. –

1

La forma más simple es llamar al q.Expression.ToString().Contains(".Where("). Como puede ver, query.Expression.ToString().Contains(".Where(") devuelve falso, mientras que queryFiltered.Expression.ToString().Contains(".Where(") devuelve verdadero.

Puede necesitar más complejidad que eso si cuenta otras expresiones como "filtrado", pero eso también es cierto con el enfoque de visitante de expresión.

Hay algo bastante raro en esto que te concederé, pero parece mucho más simple.

+0

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

+0

@xanatos ¡Ahora eso es simplemente perverso!) –

+0

@xanatos lo mismo se puede hacer para la sobrecarga de aproximación ExpressionVisitor Donde para que funcione exactamente como seleccione y pareciera que estaba filtrando donde de hecho estaría proyectando –

Cuestiones relacionadas