LINQL
editarEn C# como en la mayoría de los lenguajes de programación hay que declarar una variable antes de poder utilizarla, si no la declaramos es como si no existiera y no podríamos trabajar con ella. LINQL está basado en este lenguaje de programación. Además siempre debemos compilar y ejecutar con F5. EL primer paso para trabajar con LINQ es declarar una variable, especificando el origen de los datos. EN una consulta LINQ, la cláusula FROM aparece en primer lugar para introducir origen de los datos y la variable de rango.
Además, tiene que aprender un lenguaje de consultas diferente para cada tipo de origen de datos: bases de datos SQL, documentos XML y varios servicios web, entre otros. Con LINQ, una consulta es una construcción de lenguaje de primera clase, como clases, métodos y eventos.
Para un desarrollador que escribe consultas, la parte más visible de "lenguaje integrado" de LINQ es la expresión de consulta. Las expresiones de consulta se escriben con una sintaxis de consulta declarativa. Con la sintaxis de consulta, puede realizar operaciones de filtrado, ordenación y agrupamiento en orígenes de datos con el mínimo código. Utilice los mismos patrones de expresión de consulta básica para consultar y transformar datos de bases de datos SQL, conjuntos de datos de ADO .NET, secuencias y documentos XML y colecciones. NET.
En el ejemplo siguiente se muestra la operación de consulta completa. La operación completa incluye crear un origen de datos, definir la expresión de consulta y ejecutar la consulta en una instrucción foreach
.
C#
class LINQQueryExpressions
{
static void Main()
{
// Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 };
// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
// Output: 97 92 81
Información general sobre la expresión de consulta
editar- Las expresiones de consulta se pueden utilizar para consultar y transformar los datos de cualquier origen de datos habilitado para LINQ. Por ejemplo, una sola consulta puede recuperar datos de una base de datos SQL y generar una secuencia XML como salida.
- Las expresiones de consulta son fáciles de controlar porque utilizan muchas construcciones de lenguaje C# familiares.
- Todas las variables de una expresión de consulta están fuertemente tipadas, aunque en muchos casos no es necesario proporcionar el tipo explícitamente porque el compilador puede deducirlo. Para más información, vea Type Relationships in LINQ Query Operations (Relaciones entre tipos en las operaciones de consulta LINQ).
- Una consulta no se ejecuta hasta que no se realiza la iteración a través de la variable de consulta, por ejemplo, en una instrucción
foreach
. Para más información, vea Introduction to LINQ queries (Introducción a las consultas LINQ). - En tiempo de compilación, las expresiones de consulta se convierten en llamadas al método de operador de consulta estándar según las reglas establecidas en la especificación de C#. Cualquier consulta que se puede expresar con sintaxis de consulta también se puede expresar mediante sintaxis de método. Sin embargo, en la mayoría de los casos, la sintaxis de consulta es más legible y concisa. Para más información, vea Especificación del lenguaje C# e Información general sobre operadores de consulta estándar.
- Como regla al escribir consultas LINQ, se recomienda utilizar la sintaxis de consulta siempre que sea posible y la sintaxis de método cuando sea necesario. No hay diferencias semánticas ni de rendimiento entre estas dos formas diversas. Las expresiones de consulta suelen ser más legibles que las expresiones equivalentes escritas con la sintaxis de método.
- Algunas operaciones de consulta, como Count o Max, no tienen ninguna cláusula de expresión de consulta equivalente y, por tanto, deben expresarse como una llamada de método. La sintaxis de método se puede combinar con la sintaxis de consulta de varias maneras. Para más información, vea Query syntax and method syntax in LINQ (Sintaxis de consulta y sintaxis de método en LINQ).
- Las expresiones de consulta pueden compilarse en árboles de expresión o en delegados, en función del tipo al que se aplica la consulta. Las consultas IEnumerable<T> se compilan en delegados. Las consultas IQueryable y IQueryable<T> se compilan en árboles de expresión. Para más información, vea Expression trees (Árboles de expresión).
Las tres partes de una operación de consulta
editarTodas las operaciones de consulta LINQ constan de tres acciones distintas:
- Obtener el origen de datos.
- Crear la consulta.
- Ejecutar la consulta. En el siguiente ejemplo se muestra cómo se expresan las tres partes de una operación de consulta en código fuente. En el ejemplo se usa una matriz de enteros como origen de datos para su comodidad, aunque se aplican los mismos conceptos a otros orígenes de datos. En el resto de este tema se hará referencia a este ejemplo. C#
class IntroToLINQ { static void Main() { // The Three Parts of a LINQ Query: // 1. Data source. int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // 2. Query creation. // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; // 3. Query execution. foreach (int num in numQuery) { Console.Write("{0,1} ", num); } } }
En la siguiente ilustración se muestra toda la operación de consulta. En LINQ, la ejecución de la consulta es distinta de la propia consulta; en otras palabras, no ha recuperado los datos creando una variable de consulta.
El origen de datos
editarEn el ejemplo anterior, como el origen de datos es una matriz, admite implícitamente la interfaz genérica IEnumerable<T>. Este hecho implica que se puede consultar con LINQ. Una consulta se ejecuta en una instrucción foreach
, y foreach
requiere IEnumerable o IEnumerable<T>. Los tipos que admiten IEnumerable<T> o una interfaz derivada, como la interfaz genérica IQueryable<T>, se denominan tipos consultables.
Un tipo consultable no requiere ninguna modificación ni ningún tratamiento especial para actuar como origen de datos de LINQ. Si el origen de datos no está en la memoria como tipo consultable, el proveedor de LINQ debe representarlo como tal. Por ejemplo, LINQ to XML carga un documento XML en un tipo XElement que se puede consultar:
C#
// Create a data source from an XML document.
// using System.Xml.Linq;
XElement 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. 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 específica en la base de datos; el tipo del resultado de la consulta, IQueryable<T>, se deriva de IEnumerable<T>.
C#
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
// Query for customers in London.
IQueryable<Customer> custQuery =
from cust in db.Customers
where cust.City == "London"
select cust;
Para obtener más información sobre cómo crear tipos específicos de orígenes de datos, vea la documentación de los distintos proveedores de LINQ. Aun así, la regla básica es muy sencilla: un origen de datos de LINQ es cualquier objeto que admita la interfaz genérica IEnumerable<T> o una interfaz que la haya heredado.
La consulta
editarLa consulta especifica la información que se debe recuperar de los orígenes de datos. Opcionalmente, una consulta también especifica cómo se debe ordenar, agrupar y conformar esa información antes de que se devuelva. Las consultas se almacenan en una variable de consulta y se inicializan con una expresión de consulta. Para facilitar la escritura de consultas, C# ha incorporado una nueva sintaxis de consulta.
La consulta del ejemplo anterior devuelve todos los números pares de la matriz de enteros. La expresión de consulta contiene tres cláusulas: from
, where
y select
(si está familiarizado con SQL, habrá observado que el orden de las cláusulas se invierte respecto al orden de SQL). La cláusula from
especifica el origen de datos, la cláusula where
aplica el filtro y la cláusula select
especifica el tipo de los elementos devueltos. Estas y otras cláusulas de consulta se tratan con detalle en la sección Expresiones de consulta LINQ. Por ahora, lo importante es que en LINQ la variable de consulta no efectúa ninguna acción y no devuelve ningún dato. Lo único que hace es almacenar la información necesaria para generar los resultados cuando se ejecuta la consulta en algún momento posterior. Para obtener más información sobre cómo se construyen las consultas en segundo plano, vea Información general sobre operadores de consulta estándar (C#)Información general sobre operadores de consulta estándar.
Nota
editarLas consultas también se pueden expresar empleando una sintaxis de método. Para obtener más información, vea Query Syntax and Method Syntax in LINQ (Sintaxis de consulta y sintaxis de método en LINQ).
Ejecución de la consulta
editarEjecución aplazada
editarComo se ha indicado anteriormente, la variable de consulta solo almacena los comandos de consulta. La ejecución real de la consulta se aplaza hasta que se procese una iteración en la variable de consulta en una instrucción foreach
. Este concepto se conoce como ejecución aplazada y se muestra en el ejemplo siguiente:
C#
// Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
La instrucción foreach
es también donde se recuperan los resultados de la consulta. Por ejemplo, en la consulta anterior, la variable de iteración num
contiene cada valor (de uno en uno) en la secuencia devuelta.
Dado que la propia variable de consulta nunca contiene los resultados de la consulta, puede ejecutarla tantas veces como desee. Por ejemplo, se puede tener una base de datos que esté siendo actualizada de forma continua por otra aplicación. En su aplicación, se puede crear una consulta que recupere los datos más recientes y se puede ejecutar repetidamente de acuerdo con un intervalo para recuperar resultados diferentes cada vez.
Forzar la ejecución inmediata
editarLas consultas que llevan a cabo funciones de agregación en un intervalo de elementos de origen primero deben recorrer en iteración dichos elementos. Ejemplos de estas consultas son Count
, Max
, Average
y First
. Se ejecutan sin una instrucción foreach
explícita, ya que la propia consulta debe usar foreach
para poder devolver un resultado. Tenga en cuenta también que estos tipos de consultas devuelven un único valor, y no una colección IEnumerable
. La consulta siguiente devuelve un recuento de los números pares de la matriz de origen:
C#
var evenNumQuery =
from num in numbers
where (num % 2) == 0
select num;
int evenNumCount = evenNumQuery.Count();
Para forzar la ejecución inmediata de cualquier consulta y almacenar los resultados en la caché, puede llamar al método ToList o ToArray.
C#
List<int> numQuery2 =
(from num in numbers
where (num % 2) == 0
select num).ToList();
// or like this:
// numQuery3 is still an int[]
var numQuery3 =
(from num in numbers
where (num % 2) == 0
select num).ToArray();
También puede forzar la ejecución colocando el bucle foreach
justo después de la expresión de consulta, aunque, si se llama a ToList
o a ToArray
, también se almacenan en caché todos los datos de un objeto de colección.