Supongamos que tengo una expresión IQueryable<T>
que me gustaría encapsular la definición de, almacenarla y reutilizarla o incrustarla en una consulta más grande más adelante. Por ejemplo:¿Cómo mantener la ejecución diferida de LINQ?
IQueryable<Foo> myQuery =
from foo in blah.Foos
where foo.Bar == bar
select foo;
ahora creo que solo puedo mantener ese objeto myQuery alrededor y utilizarlo como he descrito. Sin embargo, algunas cosas que no estoy seguro acerca de:
La mejor forma de parametrizar ella? Inicialmente definí esto en un método y luego devolví el
IQueryable<T>
como resultado del método. De esta forma puedo definirblah
ybar
como argumentos de método y supongo que solo crea un nuevoIQueryable<T>
cada vez. ¿Es esta la mejor manera de encapsular la lógica de unIQueryable<T>
? ¿Hay otras formas?¿Qué sucede si mi consulta se resuelve en un escalar en lugar de
IQueryable
? Por ejemplo, ¿qué ocurre si quiero que esta consulta sea exactamente como se muestra pero anexe.Any()
para que me informe si hubo resultados que coinciden? Si agrego el(...).Any()
, el resultado esbool
y se ejecuta inmediatamente, ¿no? ¿Hay alguna manera de utilizar estos operadoresQueryable
(Any
,SindleOrDefault
, etc.) sin ejecutar de inmediato? ¿Cómo maneja esto LINQ-to-SQL?
Editar: Parte 2 es realmente más de tratar de entender cuáles son las diferencias entre IQueryable<T>.Where(Expression<Func<T, bool>>)
limitación vs IQueryable<T>.Any(Expression<Func<T, bool>>)
. Parece que este último no es tan flexible cuando se crean consultas más grandes en las que se debe retrasar la ejecución. Se puede agregar el Where()
y luego otras construcciones se pueden anexar y luego finalmente ejecutar. Como el Any()
devuelve un valor escalar, parece que se ejecutará inmediatamente antes de que se pueda generar el resto de la consulta.
Suena como en el # 1, que presenta un método que esencialmente construye un nuevo 'IQueryable' cada vez que es una buena cosa * * ya que de esta manera no voy a tener problemas con su eliminación. En el n. ° 2, estoy confundido acerca de cómo LINQ-to-SQL puede traducir el operador 'Any', pero no puedo diferir. Si tuviera que usar un operador 'Any' dentro de una consulta más grande ¿se ejecuta inmediatamente allí también, o es parte de la ejecución de la consulta más grande? – mckamey
Bien, creo que ya casi estoy allí. Si tuviera que insertar un '.Any()' en una cláusula 'where', entonces no ejecutaría eso en un bucle, ¿correcto? Compilaría la expresión SQL apropiada y la enviaría hacia abajo. Entonces, en efecto, no es '.Any()' lo que impide la ejecución diferida, ya que es la forma en que se está utilizando. Básicamente, si el resultado de una consulta * completa * es un escalar, entonces el compilador cree que necesita el resultado ahora en lugar de continuar con la compilación de un 'IQueryable'. –
mckamey
@McKAMEY correcto, tan pronto como use .Any() en un contexto que no es diferible, se ejecutará. En el caso de .Where() está buscando una expresión, que es diferible, entonces estás bien. En el caso de var o el bucle foreach, esos causan la ejecución porque no son diferibles. – Joseph