Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
LINQ to SQL traduce operadores de consulta estándar a comandos SQL. El procesador de consultas de la base de datos determina la semántica de ejecución de la traducción de SQL.
Los operadores de consulta estándar se definen contra secuencias. Una secuencia se ordena y se basa en la identidad de referencia para cada elemento de la secuencia. Para obtener más información, vea Información general sobre operadores de consulta estándar (C#) o Información general sobre operadores de consulta estándar (Visual Basic).
SQL se ocupa principalmente de conjuntos de valores sin ordenar. La ordenación suele ser una operación postprocesamiento explícitamente indicada que se aplica al resultado final de una consulta en lugar de a los resultados intermedios. La identidad se define mediante 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 traducción SQL para el proveedor de SQL Server para LINQ to SQL.
Apoyo a operadores
Concat
El Concat método se define para conjuntos múltiples ordenados en los que el orden del receptor y el orden del argumento son los mismos.
Concat funciona como UNION ALL
en los conjuntos múltiples seguidos del orden común.
El último paso es ordenar en SQL antes de que se produzcan los resultados. Concat no conserva el orden de sus argumentos. Para garantizar la ordenación adecuada, debe ordenar explícitamente los resultados de Concat.
Intersect, Except, Union
Los métodos Intersect y Except están bien definidos únicamente en conjuntos. La semántica de los conjuntos múltiples no está definida.
El Union método se define para conjuntos múltiples como la concatenación desordenada de los conjuntos múltiples (de hecho, el resultado de la cláusula UNION ALL en SQL).
Take, Skip
Take y Skip métodos están bien definidos únicamente contra conjuntos ordenados. La semántica de los conjuntos no ordenados o los conjuntos múltiples no están definidos.
Nota:
Take y Skip tienen ciertas limitaciones cuando se usan en consultas en SQL Server 2000. Para obtener más información, vea la entrada "Omitir y tomar excepciones en SQL Server 2000" en Solución de problemas.
Debido a las limitaciones de ordenación en SQL, LINQ to SQL intenta mover el orden del argumento de estos métodos al resultado del método. Por ejemplo, considere la siguiente consulta LINQ to SQL:
var custQuery =
(from cust in db.Customers
where cust.City == "London"
orderby cust.CustomerID
select cust).Skip(1).Take(1);
Dim custQuery = _
From cust In db.Customers _
Where cust.City = "London" _
Order By cust.CustomerID _
Select cust Skip 1 Take 1
El código SQL generado para este código mueve el orden al final, como se indica 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]
Resulta obvio que todas las ordenación especificadas deben ser coherentes cuando Take y Skip están encadenadas. De lo contrario, los resultados no están definidos.
Tanto Take como Skip están bien definidos para argumentos enteros no negativos y constantes, según la especificación del operador de consulta estándar.
Operadores sin traducción
LINQ to SQL no traduce los métodos siguientes. La razón más común es la diferencia entre varios conjuntos y secuencias no ordenados.
Operadores | Análisis razonado |
---|---|
TakeWhile, SkipWhile | Las consultas SQL funcionan en conjuntos múltiples, no en secuencias.
ORDER BY debe ser la última cláusula aplicada a los resultados. Por este motivo, no hay ninguna traducción de uso general para estos dos métodos. |
Reverse | La traducción de este método es posible para un conjunto ordenado, pero no se traduce actualmente mediante LINQ to SQL. |
Last, LastOrDefault | La traducción de estos métodos es posible para un conjunto ordenado, pero no se traduce actualmente mediante LINQ to SQL. |
ElementAt, ElementAtOrDefault | Las consultas SQL funcionan en conjuntos múltiples, no en secuencias indexables. |
DefaultIfEmpty (sobrecarga con argumento predeterminado) | En general, no se puede especificar un valor predeterminado para una tupla arbitraria. Los valores NULL para las tuplas son posibles en algunos casos mediante uniones externas. |
Traducción de expresiones
Semántica del nulo
LINQ to SQL no impone semántica de comparación nula en SQL. Los operadores de comparación se traducen sintácticamente a sus equivalentes de SQL. Por este motivo, la semántica refleja la semántica de SQL definida por la configuración de servidor o conexión. Por ejemplo, dos valores NULL se consideran desiguales en 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 traduce consultas.
Una comparación con el literal NULL se traduce a la versión de SQL adecuada (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 agregado del Operador de Consulta Estándar se evalúa como cero para una secuencia vacía o para una secuencia que contiene solo nulos. En LINQ to SQL, la semántica de SQL se deja sin cambios y Sum se evalúa como null
en lugar de cero para una secuencia vacía o para una secuencia que solo contiene valores NULL.
Las limitaciones de SQL en los resultados intermedios se aplican a los agregados de LINQ to SQL. Las Sum cantidades de enteros de 32 bits no se calculan mediante resultados de 64 bits. Puede producirse un desbordamiento en la conversión de LINQ to SQL que realiza Sum aun cuando la implementación del operador de consulta estándar no produce un desbordamiento para la secuencia en memoria correspondiente.
Del mismo modo, la traducción LINQ to SQL de Average valores enteros se calcula como integer
, no como double
.
Argumentos de entidad
LINQ to SQL permite usar tipos de entidad en los métodos GroupBy y OrderBy. En la traducció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(c => c);
db.Customers.GroupBy(c => new { c.CustomerID, c.ContactName });
db.Customers.GroupBy(Function(c) c)
db.Customers.GroupBy(Function(c) New With {c.CustomerID, _
c.ContactName})
Argumentos igualables o comparables
La igualdad de argumentos es necesaria en la implementación de los métodos siguientes:
LINQ to SQL admite la igualdad y la comparación de argumentos planos , pero no para los argumentos que son o contienen secuencias. Un argumento plano es un tipo que se puede asignar a una fila SQL. Una proyección de uno o varios tipos de entidad que se puede determinar estáticamente que no contiene una secuencia se considera un argumento plano.
A continuación se muestran ejemplos de argumentos planos:
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 });
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})
A continuación se muestran ejemplos de argumentos no planos (jerárquicos):
// 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);
' 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)
Traducción de funciones de Visual Basic
Las siguientes funciones auxiliares que usa el compilador de Visual Basic se traducen a las funciones y operadores 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 herencia
Restricciones de la asignación de herencia
Para obtener más información, vea Cómo: Asignar jerarquías de herencia.
Herencia en consultas
Las conversión de tipos de C# solo se admite en la proyección. Las conversiones de tipos que se utilizan en otra parte no se convierten y se omiten. Aparte de los nombres de función SQL, SQL solo realiza el equivalente de Common Language Runtime (CLR). Convert 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# solo funciona localmente. No es remota.
Los operadores is
y as
, y el método GetType
no están restringidos al operador Select
. También se pueden usar en otros operadores de consulta.
Compatibilidad con SQL Server 2008
A partir de .NET Framework 3.5 SP1, LINQ to SQL admite la asignación a nuevos tipos de fecha y hora introducidos con SQL Server 2008. Sin embargo, existen algunas limitaciones para los operadores de consulta LINQ to SQL que puede usar al trabajar con valores asignados a estos nuevos tipos.
Operadores de consulta no admitidos
Los operadores de consulta siguientes no se admiten en los 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 Asignación del tipo SQL-CLR.
Compatibilidad con SQL Server 2005
LINQ to SQL no admite las siguientes características de SQL Server 2005:
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 (en comparación con 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 reescrituras para reemplazarlas por combinaciones adecuadas.
Cross Apply
y Outer Apply
se generan para la navegación de relaciones. El conjunto de consultas para las que es posible reescribir no está bien definido. Por este motivo, 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 text
/ ntext
de datos no se pueden usar en determinadas operaciones de consulta en varchar(max)
/ nvarchar(max)
, que son compatibles con Microsoft SQL Server 2005.
No hay ninguna resolución disponible para esta limitación. En concreto, no se puede usar Distinct()
en ningún resultado que contenga miembros asignados a las 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 desencadena estas idiosincrasias no está bien definido. Por este motivo, no puede definir el conjunto de consultas LINQ to SQL que podrían provocar excepciones de SQL Server.
Operadores Skip y Take
Take y Skip tienen ciertas limitaciones cuando se usan en consultas en SQL Server 2000. Para obtener más información, vea la entrada "Omitir y tomar excepciones en SQL Server 2000" en Solución de problemas.
Materialización de objetos
La materialización crea objetos CLR a partir de filas devueltas por una o varias consultas SQL.
Las siguientes llamadas se ejecutan localmente como parte de la materialización:
Constructores
Métodos
ToString
en las proyeccionesConversiones de tipos en las proyecciones
Los métodos que siguen el AsEnumerable método se ejecutan localmente. Este método no provoca la ejecución inmediata.
Puede usar
struct
como tipo de valor devuelto de un resultado de consulta o como miembro del tipo de resultado. Las entidades deben ser clases. Los tipos anónimos se materializan como instancias de clase, pero se pueden usar estructuras con nombre (no entidades) 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: