Compartir a través de


Escribir la primera consulta con 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 consultas dedicado. A lo largo del tiempo se han ido desarrollando lenguajes diferentes para los distintos tipos de orígenes de datos, como SQL para las bases de datos relacionales y XQuery para XML. De esta manera, el desarrollador de aplicaciones debe aprender un nuevo lenguaje de consultas para cada tipo de origen de datos o formato de datos admitido.

Language-Integrated Query (LINQ) simplifica esta situación al proporcionar un modelo coherente para trabajar con los datos de varios formatos y orígenes de datos. En una consulta LINQ, siempre se trabaja con objetos. Se utilizan los mismos modelos de codificación básicos para consultar y transformar los datos de documentos XML, bases de datos SQL, conjuntos de datos y entidades de ADO.NET, colecciones de .NET Framework y cualquier otro formato u origen de datos para el que haya un proveedor LINQ disponible. En este documento se describen las tres fases para crear y utilizar consultas LINQ básicas.

vínculo a vídeo Para obtener una demostración de vídeo relacionada, vea How Do I: Get Started with LINQ?.

Las tres etapas de una operación de consulta

Las operaciones de consulta LINQ se componen de tres acciones:

  1. Obtención de uno o varios orígenes de datos.

  2. Creación de la consulta.

  3. Ejecución de la consulta.

En LINQ, la ejecución y la creación de una consulta son operaciones distintas. Por el simple hecho de crear una consulta, no se recuperan datos. Este punto se analiza con más detalle más adelante, en este mismo tema.

En el ejemplo siguiente se muestran las tres partes de una operación de consulta. En el ejemplo se utiliza una matriz de enteros como origen de datos, cómodo a efectos 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 En.

' 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

Resultado:

0 2 4 6

El origen de datos

Dado que el origen de datos del ejemplo anterior es una matriz, se admite implícitamente la interfaz genérica IEnumerable. Es este hecho lo que permite utilizar una matriz como origen de datos para una consulta LINQ. Tipos que IEnumerable admiten o una interfaz derivada como IQueryable genérico se denomina los tipos que se pueden consultar.

Como tipo que se puede consultar implícitamente, la matriz no requiere modificaciones ni un tratamiento especial para actuar como origen de datos LINQ. Lo mismo sucede con cualquier tipo de colección que admita IEnumerable, incluidos List genérico, Dictionary, y otras clases de la biblioteca de clases de .NET Framework.

Si los datos de origen no ya implementan IEnumerable, un proveedor de LINQ es necesario 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 XElement que se pueda consultar, 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.

' 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 el Object Relational Designer. Después, se escriben las consultas en los objetos y, en tiempo de ejecución, LINQ to SQL controla la comunicación con la base de datos. En el ejemplo siguiente, customers representa una tabla concreta de la base de datos y Table admite la interfaz genérica IQueryable.

' 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 de orígenes de datos específicos, consulte la documentación de los distintos proveedores LINQ. (Para obtener una lista de estos proveedores, vea LINQ (Language-Integrated Query).) La regla básica es simple: un origen de datos LINQ es cualquier objeto que admite la interfaz genérica IEnumerable o una interfaz que herede de ella.

Nota

También se pueden utilizar tipos como ArrayList, que admite la interfaz no genérica IEnumerable, como orígenes de datos LINQ.Para obtener un ejemplo donde se usa ArrayList, vea Cómo: Consultar un objeto ArrayList con LINQ.

La consulta

En la consulta se especifica qué información se desea recuperar del origen o de los orígenes de datos. También tiene la opción de especificar cómo se debería ordenar, agrupar o estructurar esa información antes de devolverse. Para habilitar la creación de consultas, Visual Basic incorpora nueva sintaxis de consulta en el 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, Where y Select. La función y el propósito específicos de cada una de las cláusulas de las expresiones de consulta se analiza en Operaciones básicas de consulta (Visual Basic). Para obtener más información, vea Consultas de Visual Basic. Observe que en LINQ una definición de consulta suele almacenarse en una variable y se ejecuta después. La variable de consulta, como evensQuery en el ejemplo anterior, debe ser un tipo que se puede consultar. El tipo de evensQuery es IEnumerable(Of Integer), asignado por el compilador mediante la inferencia de tipo de variable local.

Es importante recordar que la propia variable de consulta no realiza ninguna acción ni devuelve datos. Sólo almacena la definición de la consulta. En el ejemplo anterior, es el bucle For Each el que ejecuta la consulta.

Ejecución de la consulta

La ejecución de la consulta es proceso independiente de su creación. La creación de la consulta la define, pero su ejecución la desencadena un mecanismo diferente. Se puede ejecutar un consulta en cuanto esté definida (ejecución inmediata), o se puede guardar la definición y ejecutar la consulta más tarde (ejecución aplazada).

Ejecución diferida

Una consulta LINQ típica se parece a la del ejemplo anterior, en el que se define evensQuery. En él se crea la consulta, pero no se ejecuta de inmediato. La definición de la consulta se almacena en la variable de consulta evensQuery. La consulta se ejecuta más adelante, normalmente mediante un bucle For Each, que devuelve una secuencia de valores, o aplicando un operador de consulta estándar, como Count o Max. Este proceso se denomina ejecución aplazada.

' 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 tiene acceso a los datos recuperados mediante la variable de iteración del bucle For Each (number en el ejemplo anterior). Dado que la variable de consulta, evensQuery, contiene la definición de la consulta en lugar de los resultados, puede ejecutar una consulta tantas veces como desee, utilizando la variable de consulta. Por ejemplo, podría tener una base de datos en su aplicación que sea actualizada continuamente por una aplicación independiente. Después de haber creado una consulta que recupere los datos de esa base de datos, puede utilizar un bucle For Each para ejecutar la consulta una y otra vez, recuperando en cada ocasión los datos más recientes.

En el siguiente ejemplo se muestra cómo funciona la ejecución diferida. Una vez definida evensQuery2 y ejecutada con un bucle For Each, como en los ejemplos anteriores, algunos elementos del origen de datos numbers cambian. A continuación, un segundo bucle For Each vuelve a ejecutar evensQuery2. Los resultados son diferentes la segunda vez, porque el bucle For Each ejecuta la consulta otra vez, utilizando 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()

Resultado:

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 la consulta se almacena en una variable de consulta para su posterior ejecución. En la ejecución inmediata, la consulta se ejecuta en el momento de su definición. La ejecución se activa al aplicar un método que requiere acceso a los elementos individuales del resultado de la consulta. La ejecución inmediata se fuerza mediante el uso de uno de los operadores de consulta estándar que devuelven valores únicos. Algunos ejemplos son Count, Max, Average y 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 la consulta no se guarda y numEvens es un Integer simple.

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

Se puede conseguir el mismo resultado utilizando el método Aggregate.

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 (ejecución inmediata) o variable de consulta (ejecución 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.

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

También puede provocar la ejecución de una consulta mediante el uso de un método IEnumerable, como el método System#Collections#IEnumerable#GetEnumerator.

Demostraciones de vídeo relacionadas

How Do I: Get Started with LINQ?

Video How to: Writing Queries in Visual Basic

Vea también

Tareas

Ejemplos de LINQ

Conceptos

Información general sobre Object Relational Designer

Inferencia de tipo de variable local (Visual Basic)

Información general sobre operadores de consulta estándar

Introducción a LINQ en Visual Basic

Otros recursos

Introducción a LINQ en Visual Basic

LINQ en Visual Basic

Consultas de Visual Basic