2009-11-04 9 views
7

parece que puedo escribir un where x.a==1 && x.b==1 como¿Cuál es la diferencia entre las cláusulas where y el operador && en LINQ-to-SQL?

where x.a==1 
where x.b==1 

lo que tengo entendido este último se convierte en .Where(x => x.a == 1).Where(x => x.b ==1), pero ¿cómo se traduce esto a DB? ¿Cuál sería mejor en términos de optimización? Siempre puedo ver la consulta ejecutada desde el generador de perfiles, pero eso difícilmente sería una generalización, sino más bien una observación empírica única, en la que no quiero confiar.

Pasar por el espacio de nombres de System.Linq con reflector es otra opción, pero luego perderemos la oportunidad de evitar que muchas personas pasen tiempo en la misma cosa. Lo haré si no obtengo ninguna respuesta.

+2

casi duplicado de http://stackoverflow.com/questions/1648730/when-using-linq-what-is-the-difference-between-and-multiple-where-clauses –

+0

No encontré eso en mi búsqueda, pero esto es LINQ-to-SQL específico de todos modos. –

+0

el impacto en LINQ-to-Objects sería obvio, sin embargo, LINQ-to-SQL no está claro. –

Respuesta

7

Ok aquí están mis conclusiones después de pasar por la salida Reflector por un tiempo. LINQ a objetos combinan los where predicados consecutivos cuando se utiliza WhereArrayIterator o WhereListIterator haciendo que se comportan casi como & & operador, pero no tan exactamente:

Cuando se utilizan x.a==1 && x.b==1 la cláusula where se traduce en una Func<TSource, bool> con este aspecto:

bool daspredicate(TSource x) 
{ 
    return x.a==1 && x.b==1 
} 

Sin embargo, cuando usa cláusulas Where consecutivas, hay una pequeña penalización de rendimiento, al menos desde IL-aspect no JITted.Así es como se ve el código después de combinar:

bool predicate1(TSource x) 
{ 
    return x.a==1; 
} 
bool predicate2(TSource x) 
{ 
    return x.b==1; 
} 
bool daspredicate(TSource x) 
{ 
    return predicate1(x) && predicate2(x); 
} 

Como puede ver, esto implica una sobrecarga de llamadas de funciones adicionales. Esto puede ser bastante caro a menos que JIT incorpore las funciones. Estoy seguro de que hace un buen trabajo, pero ahora sabemos que el trabajo de JIT se vuelve mucho más fácil si combinamos nuestras declaraciones Where, a menos que sea necesario.

En lo que respecta al lado SQL, las consultas son las mismas. Incluso antes de la ejecución, el depurador evalúa el objeto de consulta en la misma instrucción SQL. No podía ir demasiado lejos en el espacio de nombres de Linq porque las cosas parecían mucho más complejas, pero dado que las consultas son las mismas, no debería haber penalizaciones, a diferencia del ejemplo de LINQ-a-objetos anterior.

EDITAR: He visto instancias en las que múltiples sentencias where resultan en subconsultas anidadas en el servidor SQL. Creo que es mejor ceñirse a las declaraciones individuales donde sea posible para estar seguro.

2

Depende de LINQ to SQL hacer lo correcto aquí. Esperaría que convirtiera dos cláusulas "where" en una única cláusula SQL con las dos partes unidas con "AND".

Prueba ambos, pero dudo mucho que veas alguna diferencia en el SQL generado.

OMI siempre debe mirar el SQL generado por cualquier cosa no trivial, pero la forma en que funciona LINQ sin duda anima a construir una consulta de gran tamaño por lo componen de cláusulas pequeños - por lo que realmente me esperaría solo para trabajar

+0

¡Parece que sí, gracias! –

2

Lado de la DB son idénticos. Es solo un efecto secundario de que Linq-to-SQL sea composable (es decir, puede comenzar con una consulta y luego agregarle criterios adicionales, cambiar proyecciones, etc.).

2

El código:

where x.a==1 
where x.b==1 

o

where x.a==1 && x.b==1 

es el azúcar sintáctica para C# de todos modos. Se compilará como una cadena método de LINQ

Where(...).Where(...) 

del mismo modo que lo haría probablemente adivinado, por lo que realmente duda hay alguna diferencia en el SQL generado. Intente utilizar una herramienta como Resharper de Jetbrains: incluso ofrece intellisense que le ofrece la opción de autoconvertirse entre los dos para ahorrar tiempo y volver a escribir para la prueba.

Mi preferencia es escribir consultas realmente simples como cadenas de métodos, (por ejemplo, cuando solo hay 1 colección/tabla involucrada y sin uniones) y algo más complicado en la sintaxis de azúcar Linq más expresiva.

+0

Aparentemente no son muy idénticos, ver mi respuesta. –

Cuestiones relacionadas