Compartir a través de


Escritura de la primera consulta LINQ (Visual Basic)

Una consulta es una expresión que recupera datos de un origen de datos. Las consultas se expresan en un lenguaje de consulta dedicado. Con el tiempo, se han desarrollado diferentes lenguajes para diferentes tipos de orígenes de datos, por ejemplo, SQL para bases de datos relacionales y XQuery para XML. Esto hace necesario que el desarrollador de aplicaciones aprenda un nuevo lenguaje de consulta para cada tipo de origen de datos o formato de datos compatible.

Language-Integrated Query (LINQ) simplifica la situación al ofrecer un modelo coherente para trabajar con datos en varios tipos de orígenes de datos y formatos. En una consulta de LINQ, siempre estás trabajando con objetos. Use los mismos patrones de codificación básicos para consultar y transformar datos en documentos XML, bases de datos SQL, conjuntos de datos y entidades de ADO.NET, colecciones de .NET Framework y cualquier otro origen o formato para el que esté disponible un proveedor LINQ. En este documento se describen las tres fases de creación y uso de consultas LINQ básicas.

Tres fases de una operación de consulta

Las operaciones de consulta LINQ constan de tres acciones:

  1. Obtenga la fuente o fuentes de datos.

  2. Cree la consulta.

  3. Ejecutar la consulta.

En LINQ, la ejecución de una consulta es distinta de la creación de la consulta. No se recuperan datos simplemente mediante la creación de una consulta. Este punto se describe con más detalle más adelante en este tema.

En el ejemplo siguiente se muestran las tres partes de una operación de consulta. En el ejemplo se usa una matriz de enteros como un origen de datos conveniente para fines de demostración. Sin embargo, los mismos conceptos también se aplican a otros orígenes de datos.

Nota:

En Página Compilación, Diseñador de proyectos (Visual Basic), asegúrese de que Option Infer está establecido en Activado.

' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next

Salida:

0 2 4 6

Origen de datos

Dado que el origen de datos del ejemplo anterior es una matriz, admite implícitamente la interfaz genérica IEnumerable<T> . Es este hecho que permite usar una matriz como origen de datos para una consulta LINQ. Los tipos que admiten IEnumerable<T> o una interfaz derivada, como el genérico IQueryable<T> , se denominan tipos consultables.

Como tipo consultable implícitamente, la matriz no requiere ninguna modificación ni tratamiento especial para servir como origen de datos LINQ. Lo mismo sucede con cualquier tipo de colección que admita IEnumerable<T>, incluidas las clases genéricas List<T>, Dictionary<TKey,TValue>y otras clases de la biblioteca de clases de .NET Framework.

Si los datos de origen aún no implementan IEnumerable<T>, se necesita un proveedor LINQ para implementar la funcionalidad de los operadores de consulta estándar para ese origen de datos. Por ejemplo, LINQ to XML controla el trabajo de cargar un documento XML en un tipo consultable XElement , como se muestra en el ejemplo siguiente. Para obtener más información sobre los operadores de consulta estándar, vea Información general sobre operadores de consulta estándar (Visual Basic).

' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")

Con LINQ to SQL, primero se crea una asignación relacional de objetos en tiempo de diseño ya sea manualmente o mediante las herramientas de LINQ to SQL de Visual Studio. Eres tú quien escribe las consultas sobre los objetos, y, en tiempo de ejecución, LINQ to SQL gestiona la comunicación con la base de datos. En el siguiente ejemplo, customers representa una tabla específica de la base de datos y Table<TEntity> da soporte a elementos genéricos IQueryable<T>.

' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)

Para obtener más información sobre cómo crear tipos específicos de orígenes de datos, consulte la documentación de los distintos proveedores de LINQ. (Para obtener una lista de estos proveedores, consulte LINQ (Language-Integrated Query)). La regla básica es sencilla: un origen de datos LINQ es cualquier objeto que admita la interfaz genérica IEnumerable<T> o una interfaz que herede de él.

Nota:

Los tipos como ArrayList que admiten la interfaz no genérica IEnumerable también se pueden usar como orígenes de datos LINQ. Para obtener un ejemplo que usa un ArrayList, vea Cómo: Consultar un objeto ArrayList con LINQ (Visual Basic).

La consulta

En la consulta, especifique qué información desea obtener del origen o de los orígenes de datos. También tiene la opción de especificar cómo se debe ordenar, agrupar o estructurar esa información antes de que se devuelva. Para habilitar la creación de consultas, Visual Basic ha incorporado una nueva sintaxis de consulta al lenguaje.

Cuando se ejecuta, la consulta del ejemplo siguiente devuelve todos los números pares de una matriz de enteros, numbers.

' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation.
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution.
For Each number In evensQuery
    Console.Write(number & " ")
Next

La expresión de consulta contiene tres cláusulas: From, Wherey Select. La función y el propósito específicos de cada cláusula de expresión de consulta se describen en Operaciones básicas de consulta (Visual Basic). Para obtener más información, consulte Consultas. Tenga en cuenta que en LINQ, una definición de consulta a menudo se almacena en una variable y se ejecuta más adelante. La variable de consulta, como evensQuery en el ejemplo anterior, debe ser un tipo consultable. El tipo de evensQuery es IEnumerable(Of Integer), asignado por el compilador mediante la inferencia de tipos locales.

Es importante recordar que la propia variable de consulta no realiza ninguna acción y no devuelve ningún dato. Solo almacena la definición de consulta. En el ejemplo anterior, es el For Each bucle que ejecuta la consulta.

Ejecución de la consulta

La ejecución de consultas es independiente de la creación de consultas. La creación de consultas define la consulta, pero la ejecución se desencadena mediante un mecanismo diferente. Una consulta se puede ejecutar tan pronto como se define (ejecución inmediata), o bien se puede almacenar la definición y la consulta se puede ejecutar más adelante (ejecución diferida).

Ejecución diferida

Una consulta LINQ típica es similar a la del ejemplo anterior, en la que evensQuery se define. Crea la consulta, pero no la ejecuta inmediatamente. En su lugar, la definición de consulta se almacena en la variable evensQueryde consulta . Ejecute la consulta más adelante, normalmente mediante un For Each bucle , que devuelve una secuencia de valores o aplicando un operador de consulta estándar, como Count o Max. Este proceso se conoce como ejecución diferida.

' Query execution that results in a sequence of values.
For Each number In evensQuery
    Console.Write(number & " ")
Next

' Query execution that results in a single value.
Dim evens = evensQuery.Count()

Para una secuencia de valores, se accede a los datos recuperados mediante la variable de iteración en el For Each bucle (number en el ejemplo anterior). Dado que la variable de consulta , evensQuerycontiene la definición de consulta en lugar de los resultados de la consulta, puede ejecutar una consulta con la frecuencia que desee mediante la variable de consulta más de una vez. Por ejemplo, puede tener una base de datos en la aplicación que se actualiza continuamente mediante una aplicación independiente. Después de crear una consulta que recupere datos de esa base de datos, puede usar un For Each bucle para ejecutar la consulta repetidamente y recuperar los datos más recientes cada vez.

En el ejemplo siguiente se muestra cómo funciona la ejecución diferida. Una vez que evensQuery2 se define y se ejecuta en un bucle For Each, como en los ejemplos anteriores, se cambian algunos elementos en el origen de datos numbers. A continuación, un segundo bucle For Each ejecuta evensQuery2 de nuevo. Los resultados son diferentes la segunda vez, ya que el For Each bucle vuelve a ejecutar la consulta mediante los nuevos valores de numbers.

Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}

Dim evensQuery2 = From num In numberArray
                  Where num Mod 2 = 0
                  Select num

Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8

' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

Salida:

Evens in original array:

0 2 4 6

Evens in changed array:

0 10 2 22 8

Ejecución inmediata

En la ejecución diferida de consultas, la definición de consulta se almacena en una variable de consulta para su ejecución posterior. En ejecución inmediata, la consulta se ejecuta en el momento de su definición. La ejecución se desencadena cuando se aplica un método que requiere acceso a elementos individuales del resultado de la consulta. La ejecución inmediata a menudo se fuerza mediante uno de los operadores de consulta estándar que devuelven valores únicos. Algunos ejemplos son Count, Max, Averagey First. Estos operadores de consulta estándar ejecutan la consulta en cuanto se aplican para calcular y devolver un resultado singleton. Para obtener más información sobre los operadores de consulta estándar que devuelven valores únicos, vea Operaciones de agregación, Operaciones de elementos y Operaciones cuantificadoras.

La consulta siguiente devuelve un recuento de los números pares de una matriz de enteros. La definición de consulta no se guarda y numEvens es un sencillo Integer.

Dim numEvens = (From num In numbers
                Where num Mod 2 = 0
                Select num).Count()

Puede lograr el mismo resultado mediante el Aggregate método .

Dim numEvensAgg = Aggregate num In numbers
                  Where num Mod 2 = 0
                  Select num
                  Into Count()

También puede forzar la ejecución de una consulta llamando al método ToList o ToArray en una consulta inmediata o en una variable de consulta diferida, como se muestra en el código siguiente.

' Immediate execution.
Dim evensList = (From num In numbers
                 Where num Mod 2 = 0
                 Select num).ToList()

' Deferred execution.
Dim evensQuery3 = From num In numbers
                  Where num Mod 2 = 0
                  Select num
' . . .
Dim evensArray = evensQuery3.ToArray()

En los ejemplos anteriores, evensQuery3 es una variable de consulta, pero evensList es una lista y evensArray es una matriz.

Usar ToList o ToArray forzar la ejecución inmediata es especialmente útil en escenarios en los que desea ejecutar la consulta inmediatamente y almacenar en caché los resultados en un único objeto de colección. Para obtener más información sobre estos métodos, vea Convertir tipos de datos.

También puede hacer que se ejecute una consulta mediante un IEnumerable método como el IEnumerable.GetEnumerator método .

Consulte también