stringtranslate.com

Consulta integrada de lenguaje

Language Integrated Query ( LINQ , pronunciado "link") es un componente de Microsoft .NET Framework que agrega capacidades de consulta de datos nativas a los lenguajes .NET , lanzado originalmente como una parte importante de .NET Framework 3.5 en 2007.

LINQ extiende el lenguaje mediante la adición de expresiones de consulta , que son similares a las sentencias SQL , y se pueden utilizar para extraer y procesar cómodamente datos de matrices , clases enumerables , documentos XML , bases de datos relacionales y fuentes de datos de terceros. Otros usos, que utilizan expresiones de consulta como un marco general para componer de forma legible cálculos arbitrarios, incluyen la construcción de controladores de eventos [1] o analizadores monádicos . [2] También define un conjunto de nombres de métodos (llamados operadores de consulta estándar u operadores de secuencia estándar ), junto con reglas de traducción utilizadas por el compilador para traducir expresiones de sintaxis de consulta en expresiones que utilizan estilo fluido (llamado sintaxis de método por Microsoft) con estos nombres de método, expresiones lambda y tipos anónimos .

Arquitectura

API de operador de consulta estándar

A continuación, las descripciones de los operadores se basan en la aplicación del trabajo con colecciones. Muchos de los operadores toman otras funciones como argumentos. Estas funciones pueden proporcionarse en forma de un método con nombre o una función anónima.

El conjunto de operadores de consulta definidos por LINQ se expone al usuario como la API de Operadores de consulta estándar (SQO) . Los operadores de consulta admitidos por la API son: [3]

Seleccionar
El operador Select realiza una proyección sobre la colección para seleccionar aspectos interesantes de los elementos. El usuario proporciona una función arbitraria, en forma de expresión con nombre o lambda , que proyecta los miembros de datos. La función se pasa al operador como un delegado . Esto implementa la función de orden superior Map .
Dónde
El operador Where permite definir un conjunto de reglas de predicado que se evalúan para cada objeto de la colección, mientras que los objetos que no coinciden con la regla se filtran. El predicado se proporciona al operador como un delegado. Esto implementa la función de orden superior Filter .
SeleccionarMuchos
Para una asignación proporcionada por el usuario de elementos de una colección a colecciones, se realizan dos pasos semánticamente. Primero, cada elemento se asigna a su colección correspondiente. Segundo, el resultado del primer paso se aplana en un nivel. Select y Where son implementables en términos de SelectMany, siempre que haya colecciones vacías y singleton disponibles. Las reglas de traducción mencionadas anteriormente aún hacen obligatorio que un proveedor LINQ proporcione los otros dos operadores. Esto implementa la función de orden superior de enlace .
Suma / Mín / Máx / Promedio

Estos operadores toman opcionalmente una función que recupera un valor numérico determinado de cada elemento de la colección y lo utiliza para encontrar la suma, el valor mínimo, el valor máximo o el valor promedio de todos los elementos de la colección, respectivamente. Las versiones sobrecargadas no toman ninguna función y actúan como si la identidad se diera como lambda.

Agregar

Una suma/mín./máx. generalizada. Este operador utiliza una función que especifica cómo se combinan dos valores para formar un resultado intermedio o final. Opcionalmente, se puede proporcionar un valor inicial, lo que permite que el tipo de resultado de la agregación sea arbitrario. Además, se puede proporcionar una función de finalización, que lleva el resultado de la agregación a otro valor. Esto implementa la función de orden superior Fold .

Unirse / Unirse al grupo
El operador Join realiza una unión interna en dos colecciones, en función de las claves coincidentes de los objetos de cada colección. Utiliza dos funciones como delegados, uno para cada colección, que ejecuta en cada objeto de la colección para extraer la clave del objeto. También utiliza otro delegado en el que el usuario especifica qué elementos de datos, de los dos elementos coincidentes, se deben utilizar para crear el objeto resultante. El operador GroupJoin realiza una unión de grupo . Al igual que el operador Select, los resultados de una unión son instancias de una clase diferente, con todos los miembros de datos de ambos tipos de los objetos de origen, o un subconjunto de ellos.
Tomar / TomarMientras
El operador Take selecciona los primeros n objetos de una colección, mientras que el operador TakeWhile, que toma un predicado, selecciona aquellos objetos que coinciden con el predicado (deteniéndose en el primer objeto que no coincide).
Saltar / SaltarMientras
Los operadores Skip y SkipWhile son complementos de Take y TakeWhile: omiten los primeros n objetos de una colección, o aquellos objetos que coinciden con un predicado (para el caso de SkipWhile).
De tipo
El operador OfType se utiliza para seleccionar los elementos de un tipo determinado.
Concat
El operador Concat concatena dos colecciones.
OrdenarPor / LuegoPor
El operador OrderBy se utiliza para especificar el orden de clasificación principal de los elementos de una colección según alguna clave. El orden predeterminado es ascendente; para invertir el orden, se debe utilizar el operador OrderByDescending . ThenBy y ThenByDescending especifican el orden posterior de los elementos. El usuario especifica como delegado la función para extraer el valor de la clave del objeto.
Contrarrestar
El operador Reverse invierte una colección.
Agrupar por
El operador GroupBy utiliza una función que extrae un valor clave y devuelve una colección de IGrouping<Key, Values>objetos para cada valor clave distinto. Los IGroupingobjetos se pueden utilizar para enumerar todos los objetos para un valor clave en particular.
Distinto
El operador Distinct elimina instancias duplicadas de un objeto de una colección. Una sobrecarga del operador toma un objeto comparador de igualdad que define los criterios de distinción.
Unión / Intersección / Excepto
Estos operadores se utilizan para realizar operaciones de unión , intersección y diferencia en dos secuencias, respectivamente. Cada uno tiene una sobrecarga que toma un objeto comparador de igualdad que define los criterios de igualdad de elementos.
SecuenciaIgual
El operador SequenceEqual determina si todos los elementos de dos colecciones son iguales y están en el mismo orden.
Primero / PrimeroOPredeterminado / Último / ÚltimoOPredeterminado
Estos operadores toman un predicado. El operador First devuelve el primer elemento para el cual el predicado devuelve verdadero o, si no hay nada que coincida, lanza una excepción. El operador FirstOrDefault es como el operador First, excepto que devuelve el valor predeterminado para el tipo de elemento (normalmente una referencia nula) en caso de que no haya nada que coincida con el predicado. El operador last recupera el último elemento que coincide con el predicado o lanza una excepción en caso de que no haya nada que coincida. El operador LastOrDefault devuelve el valor predeterminado del elemento si no hay nada que coincida.
Soltero
El operador Single toma un predicado y devuelve el elemento que coincide con el predicado. Se genera una excepción si ninguno o más de un elemento coincide con el predicado.
Único o predeterminado
El operador SingleOrDefault toma un predicado y devuelve el elemento que coincide con el predicado. Si más de un elemento coincide con el predicado, se genera una excepción. Si ningún elemento coincide con el predicado, se devuelve un valor predeterminado.
ElementoAt
El operador ElementAt recupera el elemento en un índice dado en la colección.
Cualquiera / Todos
El operador Any comprueba si hay elementos en la colección que coincidan con el predicado. No selecciona el elemento, pero devuelve verdadero si coincide al menos un elemento. Una invocación de any sin un predicado devuelve verdadero si la colección no está vacía. El operador All devuelve verdadero si todos los elementos coinciden con el predicado.
Contiene
El operador Contiene verifica si la colección contiene un elemento determinado.
Contar
El operador Count cuenta la cantidad de elementos de la colección dada. Una sobrecarga que toma un predicado cuenta la cantidad de elementos que coinciden con el predicado.

La API del operador de consulta estándar también especifica ciertos operadores que convierten una colección en otro tipo: [3]

Extensiones de lenguaje

Si bien LINQ se implementa principalmente como una biblioteca para .NET Framework 3.5, también define extensiones de lenguaje opcionales que hacen de las consultas una construcción de lenguaje de primera clase y proporcionan sintaxis para escribir consultas. Estas extensiones de lenguaje se implementaron inicialmente en C# 3.0, [5] : 75  VB 9.0 , F# [6] y Oxygene , y otros lenguajes como Nemerle han anunciado soporte preliminar. Las extensiones de lenguaje incluyen: [7]

Por ejemplo, en la consulta para seleccionar todos los objetos de una colección con SomePropertymenos de 10,

var resultados = de c en SomeCollection donde c . SomeProperty < 10 seleccione nuevo { c . SomeProperty , c . OtherProperty };              foreach ( var resultado en resultados ) { Console.WriteLine ( resultado ) ; }     

Los tipos de variables result , c y results son todos inferidos por el compilador de acuerdo con las firmas de los métodos finalmente utilizados. La base para elegir los métodos está formada por la expresión de consulta de traducción libre result

var resultados = SomeCollection . Donde ( c => c . SomeProperty < 10 ) . Select ( c => new { c . SomeProperty , c . OtherProperty });             resultados . ForEach ( x => { Console . WriteLine ( x . ToString ());})  

Proveedores LINQ

La especificación C#3.0 define un patrón de expresión de consulta junto con reglas de traducción de una expresión LINQ a una expresión en un subconjunto de C# 3.0 sin expresiones LINQ. La traducción así definida no tiene tipo, lo que, además de que las expresiones lambda se pueden interpretar como delegados o árboles de expresión, permite un alto grado de flexibilidad para las bibliotecas que desean exponer partes de su interfaz como cláusulas de expresión LINQ. Por ejemplo, LINQ to Objects funciona en IEnumerable<T>s y con delegados, mientras que LINQ to SQL utiliza los árboles de expresión.

Los árboles de expresión son el núcleo del mecanismo de extensibilidad de LINQ, mediante el cual LINQ se puede adaptar a muchas fuentes de datos. Los árboles de expresión se entregan a los proveedores de LINQ, que son implementaciones específicas de la fuente de datos que adaptan las consultas LINQ para que se utilicen con la fuente de datos. Si así lo deciden, los proveedores de LINQ analizan los árboles de expresión contenidos en una consulta para generar las piezas esenciales necesarias para la ejecución de una consulta. Pueden ser fragmentos de SQL o cualquier otra representación de código completamente diferente como datos manipulables adicionales. LINQ viene con proveedores de LINQ para colecciones de objetos en memoria, bases de datos de Microsoft SQL Server , conjuntos de datos ADO.NET y documentos XML. Estos diferentes proveedores definen los diferentes tipos de LINQ:

LINQ a objetos

El proveedor LINQ to Objects se utiliza para colecciones en memoria, utilizando el motor de ejecución de consultas local de LINQ. El código generado por este proveedor hace referencia a la implementación de los operadores de consulta estándar tal como se define en el Sequencepatrón y permite IEnumerable<T>que las colecciones se consulten localmente. La implementación actual de LINQ to Objects realiza comprobaciones de implementación de interfaz para permitir pruebas de pertenencia rápidas, recuentos y operaciones de búsqueda indexada cuando son compatibles con el tipo de tiempo de ejecución de IEnumerable. [8] [9] [10]

LINQ to XML (antes llamado XLINQ)

El proveedor LINQ to XML convierte un documento XML en una colección de XElementobjetos, que luego se consultan utilizando el motor de ejecución local que se proporciona como parte de la implementación del operador de consulta estándar. [11]

LINQ to SQL (antes llamado DLINQ)

El proveedor LINQ to SQL permite utilizar LINQ para consultar bases de datos de Microsoft SQL Server , incluidas las bases de datos SQL Server Compact . Dado que los datos de SQL Server pueden residir en un servidor remoto y que SQL Server tiene su propio motor de consultas, LINQ to SQL no utiliza el motor de consultas de LINQ. En su lugar, convierte una consulta LINQ en una consulta SQL que luego se envía a SQL Server para su procesamiento. [12] Sin embargo, dado que SQL Server almacena los datos como datos relacionales y LINQ trabaja con datos encapsulados en objetos, las dos representaciones deben asignarse entre sí. Por este motivo, LINQ to SQL también define un marco de asignación. La asignación se realiza definiendo clases que corresponden a las tablas de la base de datos y que contienen todas o un subconjunto de las columnas de la tabla como miembros de datos. [13] La correspondencia, junto con otros atributos del modelo relacional , como las claves principales , se especifican utilizando atributos definidos por LINQ to SQL . Por ejemplo,

[Tabla(Nombre="Clientes")] clase pública Cliente { [Columna(IsPrimaryKey = true)] int público CustID ;       [Columna] cadena pública CustName ; }   

Esta definición de clase se asigna a una tabla denominada Customersy los dos miembros de datos corresponden a dos columnas. Las clases deben definirse antes de poder utilizar LINQ to SQL. Visual Studio 2008 incluye un diseñador de asignaciones que se puede utilizar para crear la asignación entre los esquemas de datos en el objeto, así como el dominio relacional. Puede crear automáticamente las clases correspondientes a partir de un esquema de base de datos , así como permitir la edición manual para crear una vista diferente utilizando solo un subconjunto de las tablas o columnas de una tabla. [13]

El mapeo se implementa mediante el DataContextque toma una cadena de conexión al servidor y se puede utilizar para generar un Table<T>donde T es el tipo al que se mapeará la tabla de la base de datos. El Table<T>encapsula los datos en la tabla e implementa la IQueryable<T>interfaz, de modo que se crea el árbol de expresiones, que maneja el proveedor LINQ to SQL. Convierte la consulta en T-SQL y recupera el conjunto de resultados del servidor de la base de datos. Dado que el procesamiento ocurre en el servidor de la base de datos, no se pueden utilizar los métodos locales, que no están definidos como parte de las expresiones lambda que representan los predicados. Sin embargo, puede utilizar los procedimientos almacenados en el servidor. Se realiza un seguimiento de cualquier cambio en el conjunto de resultados y se puede enviar de vuelta al servidor de la base de datos. [13]

LINQ a conjuntos de datos

Dado que el proveedor LINQ to SQL (arriba) funciona únicamente con bases de datos de Microsoft SQL Server , para poder admitir cualquier base de datos genérica, LINQ también incluye LINQ to DataSets. Utiliza ADO.NET para gestionar la comunicación con la base de datos. Una vez que los datos están en los conjuntos de datos ADO.NET, LINQ to DataSets ejecuta consultas en estos conjuntos de datos. [14]

Actuación

Los usuarios no profesionales pueden tener dificultades con las sutilezas de las características y la sintaxis de LINQ to Objects . Los patrones de implementación ingenuos de LINQ pueden provocar una degradación catastrófica del rendimiento. [15] [16]

El rendimiento de LINQ to XML y LINQ to SQL en comparación con ADO.NET depende del caso de uso. [17] [18]

PLINQ

La versión 4 del marco .NET incluye PLINQ , o Parallel LINQ , un motor de ejecución paralela para consultas LINQ. Define la ParallelQuery<T>clase. Cualquier implementación de la IEnumerable<T>interfaz puede aprovechar el motor PLINQ llamando al AsParallel<T>(this IEnumerable<T>)método de extensión definido por la clase ParallelEnumerable en el espacio de nombres System.Linq del marco .NET. [19] El motor PLINQ puede ejecutar partes de una consulta simultáneamente en varios subprocesos, lo que proporciona resultados más rápidos. [20]

Lenguas predecesoras

Muchos de los conceptos que introdujo LINQ se probaron originalmente en el proyecto de investigación de Microsoft , anteriormente conocido con los nombres en código X# (X Sharp) y Xen . Se le cambió el nombre a Cω después de que se integrara en él Polyphonic C# (otro lenguaje de investigación basado en principios de cálculo de uniones ).

Cω intenta hacer que los almacenes de datos (como bases de datos y documentos XML ) sean accesibles con la misma facilidad y seguridad de tipos que los tipos tradicionales como cadenas y matrices . Muchas de estas ideas fueron heredadas de un proyecto de incubación anterior dentro del equipo WebData XML llamado X# y Xen. Cω también incluye nuevas construcciones para soportar la programación concurrente ; estas características se derivaron en gran medida del proyecto anterior Polyphonic C#. [21]

Disponible por primera vez en 2004 como una vista previa del compilador, las características de Cω fueron posteriormente utilizadas por Microsoft en la creación de las características LINQ lanzadas en 2007 en la versión 3.5 de .NET [22] Las construcciones de concurrencia también han sido lanzadas en una forma ligeramente modificada como una biblioteca, llamada Joins Concurrency Library , para C# y otros lenguajes .NET por Microsoft Research . [23]

Puertos

Existen puertos de LINQ para PHP (PHPLinq), JavaScript (linq.js), TypeScript (linq.ts) y ActionScript (ActionLinq), aunque ninguno es estrictamente equivalente a LINQ en los lenguajes inspirados en .NET C#, F# y VB.NET (donde es parte del lenguaje, no una biblioteca externa, y donde a menudo aborda una gama más amplia de necesidades). [ cita requerida ]

Véase también

Referencias

  1. ^ "Marco Rx". 10 de junio de 2011.
  2. ^ "Combinadores de analizadores monádicos con C#3" . Consultado el 21 de noviembre de 2009 .
  3. ^ ab "Operadores de consulta estándar". Microsoft . Consultado el 30 de noviembre de 2007 .
  4. ^ "Clase enumerable". msdn . Microsoft . Consultado el 15 de febrero de 2014 .
  5. ^ ab Skeet, Jon (23 de marzo de 2019). C# en profundidad . Manning. ISBN 978-1617294532.
  6. ^ "Expresiones de consulta (F#)". Microsoft Docs . Consultado el 19 de diciembre de 2012 .
  7. ^ "LINQ Framework" . Consultado el 30 de noviembre de 2007 .
  8. ^ "Enumerable.ElementAt" . Consultado el 7 de mayo de 2014 .
  9. ^ "Enumerable.Contains" . Consultado el 7 de mayo de 2014 .
  10. ^ "Enumerable.Count" . Consultado el 7 de mayo de 2014 .
  11. ^ "Consulta integrada en lenguaje .NET para datos XML". 30 de abril de 2007. Consultado el 30 de noviembre de 2007 .
  12. ^ "LINQ to SQL". Archivado desde el original el 25 de enero de 2013. Consultado el 30 de noviembre de 2007 .
  13. ^ abc "LINQ to SQL: consulta integrada en el lenguaje .NET para datos relacionales". 30 de abril de 2007. Consultado el 30 de noviembre de 2007 .
  14. ^ "LINQ to DataSets". Archivado desde el original el 25 de enero de 2013. Consultado el 30 de noviembre de 2007 .
  15. ^ Vider, Guy (21 de diciembre de 2007). "Prueba de rendimiento de LINQ: mi primer proyecto de Visual Studio 2008" . Consultado el 8 de febrero de 2009 .
  16. ^ Parsons, Jared (2008). "Increase LINQ Query Performance" (Aumentar el rendimiento de las consultas LINQ). Microsoft Developer Network . Consultado el 19 de marzo de 2014. Si bien es cierto que LINQ es potente y muy eficiente, los grandes conjuntos de datos aún pueden causar problemas de rendimiento inesperados.
  17. ^ Alva, Jaime (2010-08-06). "Potential Performance Issues with Compiled LINQ Query Re-Compiles". Microsoft Developer Network . Consultado el 19 de marzo de 2014. Al llamar a una consulta varias veces con Entity Framework, el enfoque recomendado es utilizar consultas LINQ compiladas. La compilación de una consulta da como resultado un impacto en el rendimiento la primera vez que se utiliza la consulta, pero las llamadas posteriores se ejecutan mucho más rápido.
  18. ^ Kshitij, Pandey (25 de mayo de 2008). "Comparaciones de rendimiento de LinQ con SQL, ADO y C#" . Consultado el 8 de febrero de 2009 .
  19. ^ "Clase ParallelEnumerable" . Consultado el 7 de mayo de 2014 .
  20. ^ "Programación en la era de la concurrencia: programación concurrente con PFX" . Consultado el 16 de octubre de 2007 .
  21. ^ Eichert, Steve; Wooley, James B.; Marguerie, Fabrice (2008). LINQ in Action . Manning. pp. 56–57 (como se informa en el enlace de búsqueda de Google Books; el libro no tiene números de página). ISBN 9781638354628.
  22. ^ Conceptos detrás del lenguaje C# 3.0 | Artículos | TomasP.Net Archivado el 12 de febrero de 2007 en Wayback Machine
  23. ^ "La biblioteca de concurrencia de uniones" . Consultado el 8 de junio de 2007 .

Enlaces externos