sábado, 27 de agosto de 2011

Sintaxis de método en LINQ

Como ya vimos en el post Distintas sintaxis de Linq, cualquier expresión de consulta  expresada con la sintaxis de consulta (query syntax) es finalmente traducida en tiempo de ejecución a una expresión de consulta con sintaxis de método (method syntax)

Esto significa que la siguiente expresión de consulta con sintaxis de consulta:

                From r In Clientes

                Where r.Nombre.StartsWith("C")

                Order By r.IdCliente Descending

                Select r


Terminará siendo una expresión de consulta con la siguiente sintaxis de método:

                Clientes.

                Where(Function(r) r.Nombre.StartsWith("C")).

                OrderByDescending(Function(r) r.IdCliente).

                Select(Function(r) r)

 

Asumimos que Clientes es una variable del tipo List(Of Cliente) y que la clase Cliente tiene una propiedad IdCliente.

 

Antes de continuar, te diré que hay 2 programas que me parecen imprescindible (sobre todo sin aún no somos maestros de Linq, que es mi caso) que son:

LINQPad. Gratuita. Response a preguntas como ¿Qué sintaxis de método generará esta expresión de consulta con sintaxis de consulta? ¿Qué consulta SQL generará esta expresión de consulta LINQ?

Linquer. Es de pago, pero 60$ me parecen un dinero muy bien invertido. Convierte código T-SQL a expresiones de consulta LINQ. Imprescindible para contestar preguntas del estilo ¿Cómo hago en LINQ esta consulta que SÍ se hacer en T-SQL? ¿Qué consulta SQL generará esta expresión de consulta LINQ?

En realidad ambos programas hacen muchas más cosas de lo que te he dicho y es por eso que te recomiendo encarecidamente que los agregues a tu Toolbelt y ¡no salgas de casa sin ellos!

Volviendo al tema de sintaxis de consulta vs sintaxis de método, lo que realmente quiero explicar en este post es ¿De dónde sale LINQ?

Ya tenemos claro que la sintaxis de consulta (aquella que nos recuerda al SQL) no es más que una sintaxis amigable para llegar finalmente a la sintaxis de método (aquella que NO nos recuerda a SQL y además ¡no nos gusta!). El problema es que, justamente conociendo a esta última sintaxis será como entendamos cómo funciona LINQ y de donde sale… que no tiene nada que ver con que finalmente utilicemos la sintaxis de consulta al estilo SQL que cierto es, parece más sencilla y agradecida.

La sintaxis de método (recuerda que es la que finalmente siempre se ejecuta) espera encontrar una serie de métodos encadenados (se encadenan porque normalmente reciben una secuencia y devuelven otra secuencia para poder llevar a cabo una cascada de métodos), en los que cada uno de ellos tiene una firma específica que normalmente reciben parámetros de tipo delegados genéricos (por ello podemos utilizar expresiones lambda, recuerda que “donde se espera un delegado se puede utilizar una expresión lambda”). Todos estos métodos que intervienen en la expresión de consulta a través de sintaxis de método son llamadas “operadores de consulta” (query operators). Es decir, los métodos Where, OrderByDescending y Select (algunos de los métodos a los que se traduce finalmente cualquier expresión de consulta) son operadores de consulta (y así verás que la gente se refiere a ellos en Internet).

Si hablamos de LINQ to Objects, todos estos operadores de consulta están definidos en el ensamblado System.Core, y en la clase System.Linq.Enumerable.

Si nos fijamos en la descripción de la clase en el examinador de objetos, dice “Proporciona un conjunto de métodos static (Shared en Visual Basic) para consultar objetos que implementan System.Collections.Generic.IEnumerable(Of T).”, blanco y en botella, ¿no? Todo tipo que implemente IEnumerable(Of T) tendrá automáticamente disponibles estos métodos u operadores de consulta. Y en nuestro caso, recuerda que Clientes es del tipo List(Of T) y por ende del tipo IEnumerable(Of T), y es por eso que podemos utilizar LINQ sobre nuestra variable Clientes.

Por otro lado, si estamos utilizando LINQ to Entities, también en el ensamblado System.Core tenemos la clase System.Linq.Queryable, cuya descripción es “Proporciona un conjunto de métodos static (Shared en Visual Basic) para consultar estructuras de datos que implementan System.Linq.IQueryable(Of T)”.

Está claro que los operadores de consulta para LINQ to Objects y LINQ to Entities están en el ensamblado System.Core. Pero ¿Y por ejemplo LINQ to XML? Pues está en el ensamblado System.Xml.Linq y en la clase System.Xml.Linq.ExtensionsContiene los métodos de extensión de LINQ to XML.”.

Lo que quiero decir, es que cualquier proveedor de LINQ necesita una clase que defina métodos de extensión para los operadores de consulta, sino no hay LINQ.

De hecho, y para confirmar que LINQ es extensible (esto es que cualquiera puede meterle mano), veamos un ejemplo en el que agregaremos un método extensor a IEnumerable(Of Clientes) y así podremos utilizar este método en la “cascada de métodos” de una expresión de consulta LINQ.

Public Class GestorClientes

    Public Function GetClientes() As IEnumerable(Of Clientes)

        Using ctx As New EFEntities

            Dim t =

                (From r In ctx.Clientes

                Order By r.IdCliente Descending).ToList.SoloClientesQueComiencenPorC

            Return t

        End Using

    End Function

End Class

 

Public Module MetodosExtensionParaClientes

    <System.Runtime.CompilerServices.Extension()> _

    Public Function SoloClientesQueComiencenPorC(ByVal t As IEnumerable(Of Clientes)) As IEnumerable(Of Clientes)

        Return From r In t Where r.Nombre.StartsWith("C")

    End Function

 

End Module


A partir de aquí y sabiendo ya de donde carajo sale LINQ, nuestra obligación es conocer la lista de operadores de consulta que hay disponible.

 

Un saludo!

No hay comentarios:

Publicar un comentario