traducción de operadores de consulta estándar [LINQ to SQL]
Actualización: November 2007
LINQ to SQL convierte los operadores de consulta estándar en comandos SQL. El procesador de consultas de la base de datos determina la semántica de ejecución de la conversión a SQL.
Los operadores de consulta estándar se definen en secuencias. Una secuencia se ordena y se basa en la identidad de referencia de cada elemento de la secuencia. Para obtener más información, consulte Información general sobre operadores de consulta estándar.
SQL trata principalmente con conjuntos de valores no ordenados. La ordenación es normalmente una operación de procesamiento posterior declarada de forma explícita que se aplica al resultado final de una consulta en lugar de a los resultados intermedios. La identidad se define con valores. Por esta razón se entiende que las consultas SQL tratan con conjuntos múltiples (bolsas) en lugar de conjuntos.
En los párrafos siguientes se describen las diferencias entre los operadores de consulta estándar y su conversión a SQL para el proveedor de SQL Server de LINQ to SQL.
Compatibilidad de los operadores
Concat
El método Concat<TSource> se define para los conjuntos múltiples ordenados cuando el orden del receptor y el orden del argumento son iguales. Concat<TSource> funciona como UNION ALL sobre los conjuntos múltiples después del orden común.
El último paso es ordenar en SQL antes de que se generen los resultados. Concat<TSource> no conserva el orden de sus argumentos. Para garantizar una ordenación correcta, debe ordenar explícitamente los resultados de Concat<TSource>.
Intersect, Except, Union
Los métodos Intersect y Except se definen bien sólo en los conjuntos. La semántica de conjuntos múltiples no está definida.
El método Union se define para los conjuntos múltiples como la concatenación no ordenada de los conjuntos múltiples (de hecho, el resultado de la cláusula UNION ALL en SQL).
Take, Skip
Los métodos Take<TSource> y Skip<TSource> están bien definidos sólo en conjuntos ordenados. La semántica para los conjuntos no ordenados o conjuntos múltiples no está definida.
Nota: |
---|
Take<TSource> y Skip<TSource> tienen ciertas limitaciones cuando se utilizan en consultas en SQL Server 2000. Para obtener más información, vea la sección donde se tratan las excepciones de Skip y Take en SQL Server 2000, en el tema Solución de problemas (LINQ to SQL). |
Debido a las limitaciones de la ordenación en SQL, LINQ to SQL intenta trasladar la ordenación del argumento de estos métodos al resultado del método. Por ejemplo, considere la siguiente consulta LINQ to SQL:
Dim custQuery = _
From cust In db.Customers _
Where cust.City = "London" _
Order By cust.CustomerID _
Select cust Skip 1 Take 1
var custQuery =
(from cust in db.Customers
where cust.City == "London"
orderby cust.CustomerID
select cust).Skip(1).Take(1);
El SQL generado para este código traslada la ordenación al final, como se observa a continuación:
SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],
FROM [Customers] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP 1 [t1].[CustomerID]
FROM [Customers] AS [t1]
WHERE [t1].[City] = @p0
ORDER BY [t1].[CustomerID]
) AS [t2]
WHERE [t0].[CustomerID] = [t2].[CustomerID]
))) AND ([t0].[City] = @p1)
ORDER BY [t0].[CustomerID]
Parece obvio que toda la ordenación especificada debe ser coherente cuando se encadenan Take<TSource> y Skip<TSource>. De lo contrario, los resultados no están definidos.
Tanto Take<TSource> como Skip<TSource> están bien definidos para los argumentos integrales de constante no negativos basados en la especificación de operadores de consulta estándar.
Operadores sin conversión
LINQ to SQL no convierte los métodos siguientes. La razón más común es la diferencia entre los conjuntos múltiples no ordenados y las secuencias.
Operadores |
Razonamiento |
---|---|
Las consultas SQL funcionan con conjuntos múltiples, no con secuencias. ORDER BY debe ser la última cláusula aplicada a los resultados. Por esta razón, no hay ninguna conversión general para estos dos métodos. |
|
La conversión de este método es posible para un conjunto ordenado pero LINQ to SQL no la realiza actualmente. |
|
La conversión de estos métodos es posible para un conjunto ordenado pero LINQ to SQL no la realiza actualmente. |
|
Las consultas SQL funcionan en conjuntos múltiples, no en secuencias indizables. |
|
DefaultIfEmpty (sobrecarga con argumento predeterminado) |
En general, no se puede especificar un valor predeterminado para una tupla arbitraria. Los valores nulos para las tuplas son posibles en algunos casos a través de combinaciones externas. |
Conversión de expresiones
Semántica de valores null
LINQ to SQL no impone las semántica de comparación de valores null en SQL. Los operadores de comparación se convierten sintácticamente en sus equivalentes SQL. Por esta razón, la semántica refleja la semántica de SQL definida según la configuración del servidor o la conexión. Por ejemplo, dos valores nulos se consideran distintos según la configuración predeterminada de SQL Server, pero puede cambiar la configuración para cambiar la semántica. LINQ to SQL no tiene en cuenta la configuración del servidor cuando convierte las consultas.
Una comparación con el literal null se convierte a la versión de SQL correcta (is null o is not null).
SQL Server define el valor null en la intercalación. LINQ to SQL no cambia la intercalación.
Agregados
El método de agregado del operador de consulta estándar Sum se evalúa como cero para una secuencia vacía o para una secuencia que sólo contiene valores nulos. En LINQ to SQL, la semántica de SQL se mantiene invariable y Sum se evalúa como null en lugar de cero para una secuencia vacía o para una secuencia que sólo contiene valores nulos.
En LINQ to SQL se aplican las restricciones de SQL para los agregados en los resultados intermedios. Sum para cantidades enteras de 32 bits no se calcula utilizando los resultados de 64 bits. Puede producirse un desbordamiento en la conversión de Sum que realiza LINQ to SQL aun cuando la implementación del operador de consulta estándar no produce un desbordamiento para la secuencia en memoria correspondiente.
De igual forma, la conversión que realiza LINQ to SQL de Average de valores enteros se calcula como integer, no como double.
Argumentos de entidad
LINQ to SQL permite utilizar los tipos de entidad en los métodos GroupBy y OrderBy. En la conversión de estos operadores, el uso de un argumento de un tipo se considera equivalente a especificar todos los miembros de ese tipo. Por ejemplo, el código siguiente es equivalente:
db.Customers.GroupBy(Function(c) c)
db.Customers.GroupBy(Function(c) New With {c.CustomerID, _
c.ContactName})
db.Customers.GroupBy(c => c);
db.Customers.GroupBy(c => new { c.CustomerID, c.ContactName });
Argumentos equivalentes o comparables
La igualdad de los argumentos se requiere en la implementación de los métodos siguientes:
LINQ to SQL admite la igualdad y comparación para los argumentos planos, pero no para los argumentos que son secuencias o las contienen. Un argumento plano es un tipo que asignarse a una fila de SQL. Una proyección de uno o más tipos de entidad que se pueden determinar estáticamente que no contiene una secuencia se considera un argumento plano.
A continuación se ofrecen ejemplos de argumentos planos:
db.Customers.Select(Function(c) c)
db.Customers.Select(Function(c) New With {c.CustomerID, c.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer})
db.Customers.Select(c => c);
db.Customers.Select(c => new { c.CustomerID, c.City });
db.Orders.Select(o => new { o.OrderID, o.Customer.City });
db.Orders.Select(o => new { o.OrderID, o.Customer });
A continuación se ofrecen ejemplos de argumentos no planos (jerárquicos).
' In the following line, c.Orders is a sequence.
db.Customers.Select(Function(c) New With {c.CustomerID, c.Orders})
' In the following line, the result has a sequence.
db.Customers.GroupBy(Function(c) c.City)
// In the following line, c.Orders is a sequence.
db.Customers.Select(c => new { c.CustomerID, c.Orders });
// In the following line, the result has a sequence.
db.Customers.GroupBy(c => c.City);
Conversión de funciones de Visual Basic
Las siguientes funciones auxiliares que utiliza el compilador de Visual Basic se convierten a las funciones y operadores de SQL correspondientes:
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
Métodos de conversión:
ToBoolean |
ToSByte |
ToByte |
ToChar |
ToCharArrayRankOne |
ToDate |
ToDecimal |
ToDouble |
ToInteger |
ToUInteger |
ToLong |
ToULong |
ToShort |
ToUShort |
ToSingle |
ToString |
Compatibilidad de la herencia
Restricciones de la asignación de herencia
Para obtener más información, consulte Cómo: Asignar jerarquías de herencia (LINQ to SQL).
Herencia en consultas
Las conversión de tipos de C# sólo se admite en la proyección. Las conversiones de tipos que se utilizan en otra parte no se convierten y se omiten. Además de los nombres de función de SQL, SQL realmente sólo realiza la operación equivalente a Convert de Common Language Runtime (CLR). Es decir, SQL puede cambiar el valor de un tipo a otro. No hay ningún equivalente de conversión de tipos de CLR porque no existe el concepto de reinterpretar los mismos bits que los de otro tipo. Por esa razón una conversión de tipos de C# sólo funciona localmente. No es remota.
Los operadores, is y as, y el método GetType no están limitados al operador Select. También se pueden utilizar en otros operadores de consulta.
Compatibilidad con SQL Server 2008
A partir de .NET Framework 3.5 Service Pack 1, LINQ to SQL admite la asignación a tipos nuevos de fecha y hora incorporados con SQL Server 2008. Pero, hay algunas limitaciones en los operadores de consulta de LINQ to SQL que puede usar al operar con valores asignados a estos tipos nuevos.
Operadores de consulta no admitidos
Los operadores de consulta siguientes no se admiten en valores asignados a los nuevos tipos de fecha y hora de SQL Server: DATETIME2, DATE, TIME y DATETIMEOFFSET.
Aggregate
Average
LastOrDefault
OfType
Sum
Para obtener más información sobre la asignación a estos tipos de fecha y hora de SQL Server, vea Correspondencia de tipos SQL-CLR (LINQ to SQL).
Compatibilidad con SQL Server 2005
LINQ to SQL no admite las características de SQL Server 2005 siguientes:
Procedimientos almacenados escritos para SQL CLR.
Tipo definido por el usuario.
Características de consulta XML.
Compatibilidad con SQL Server 2000
Las siguientes limitaciones de SQL Server 2000 (frente a Microsoft SQL Server 2005) afectan a la compatibilidad con LINQ to SQL.
Operadores Cross Apply y Outer Apply
Estos operadores no están disponibles en SQL Server 2000. LINQ to SQL intenta una serie de operaciones de reescritura para sustituirlos por las combinaciones adecuadas.
Cross Apply y Outer Apply se generan para la navegación de relaciones. El conjunto de consultas para el que son posibles tales operaciones de reescritura no está bien definido. Por esta razón, el conjunto mínimo de consultas que se admite para SQL Server 2000 es el conjunto que no implica la navegación de relaciones.
text / ntext
Los tipos de datos text / ntext no se pueden utilizar en ciertas operaciones de consulta con varchar(max) / nvarchar(max), que son admitidos por Microsoft SQL Server 2005.
Esta limitación no tiene ninguna resolución. Concretamente, no puede utilizar Distinct() en ningún resultado que contenga miembros que se asignen a columnas text o ntext.
Comportamiento desencadenado por las consultas anidadas
El enlazador de SQL Server 2000 (hasta SP4) tiene algunas peculiaridades que son desencadenadas por las consultas anidadas. El conjunto de consultas SQL que las desencadenan no está bien definido. Por esta razón, no se puede definir el conjunto de consultas LINQ to SQL que podrían producir excepciones de SQL Server.
Operadores Skip y Take
Take<TSource> y Skip<TSource> tienen ciertas limitaciones cuando se utilizan en consultas en SQL Server 2000. Para obtener más información, vea la sección donde se tratan las excepciones de Skip y Take en SQL Server 2000, en el tema Solución de problemas (LINQ to SQL).
Materialización de objetos
La materialización crea objetos CLR a partir de las filas devueltas por una o más consultas SQL.
Las llamadas siguientes se ejecutan localmente como parte de la materialización:
Constructores
Métodos ToString en las proyecciones
Conversiones de tipos en las proyecciones
Los métodos que siguen al método AsEnumerable<TSource> se ejecutan localmente. Este método no produce la ejecución inmediata.
Puede utilizar struct como tipo de valor devuelto en el resultado de una consulta o como un miembro del tipo de resultado. Las entidades deben ser clases. Los tipos anónimos se materializan como instancias de clase, pero las estructuras con nombre (no entidades) se pueden utilizar en la proyección.
Un miembro del tipo de valor devuelto en el resultado de una consulta puede ser de tipo IQueryable<T>. Se materializa como una colección local.
Los métodos siguientes provocan la materialización inmediata de la secuencia a la que se aplican los métodos:
Vea también
Tareas
Cómo: Devolver u omitir elementos de una secuencia (LINQ to SQL)
Cómo: Concatenar dos secuencias (LINQ to SQL)
Cómo: Devolver la diferencia de conjuntos entre dos secuencias (LINQ to SQL)
Cómo: Devolver la intersección de conjuntos de dos secuencias (LINQ to SQL)
Cómo: Devolver la unión de conjuntos de dos secuencias (LINQ to SQL)