Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
LINQ to SQL converte operadores de consulta padrão para comandos SQL. O processador de consulta do banco de dados determina a semântica de execução da tradução SQL.
Os Operadores de Consulta Padrão são definidos para sequências. Uma sequência é ordenada e depende da identidade de referência para cada elemento da sequência. Para obter mais informações, consulte Visão geral dos operadores de consulta padrão (C#) ou visão geral dos operadores de consulta padrão (Visual Basic).
O SQL lida principalmente com conjuntos de valores não ordenados. A ordenação normalmente é uma operação pós-processamento explicitamente declarada que é aplicada ao resultado final de uma consulta em vez de a resultados intermediários. A identidade é definida por valores. Por esta razão, as consultas SQL são supostas a manipular multisets (recipientes) em vez de conjuntos.
Os parágrafos a seguir descrevem as diferenças entre os operadores de consulta padrão e sua conversão SQL do provedor SQL Server para LINQ to SQL.
Suporte ao operador
Concat
O Concat método é definido para vários conjuntos ordenados em que a ordem do receptor e a ordem do argumento são iguais.
Concat funciona como UNION ALL
em vários conjuntos seguidos pela ordem comum.
A etapa final é ordenar no SQL antes que os resultados sejam produzidos. Concat não preserva a ordem de seus argumentos. Para garantir a ordenação apropriada, você deve ordenar explicitamente os resultados de Concat.
Intersect, Except, Union
Os métodos Intersect e Except são bem definidos somente em conjuntos. A semântica para vários conjuntos é indefinida.
O Union método é definido para vários conjuntos como a concatenação não ordenada dos multiconjuntos (efetivamente o resultado da cláusula UNION ALL no SQL).
Take, Skip
Take e Skip os métodos são bem definidos somente em relação aos conjuntos ordenados. A semântica para conjuntos ou vários conjuntos não ordenados é indefinida.
Observação
Take e Skip têm certas limitações quando são usadas em consultas no SQL Server 2000. Para obter mais informações, consulte a entrada "Ignorar e aceitar exceções no SQL Server 2000" na solução de problemas.
Devido às limitações na ordenação no SQL, o LINQ to SQL tenta mover a ordenação do argumento desses métodos para o resultado do método. Por exemplo, considere a seguinte 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
O SQL gerado para esse código move a ordenação para o final, da seguinte maneira:
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]
Torna-se óbvio que todos os pedidos especificados devem ser consistentes quando Take e Skip são encadeados juntos. Caso contrário, os resultados serão indefinidos.
Ambos Take e Skip são bem definidos para argumentos integrais constantes não negativos com base na especificação do Operador de Consulta Padrão.
Operadores sem tradução
Os métodos a seguir não são traduzidos pelo LINQ para SQL. O motivo mais comum é a diferença entre multiconjuntos e sequências não ordenados.
Operadores | Fundamento |
---|---|
TakeWhile, SkipWhile | As consultas SQL operam em vários conjuntos, não em sequências.
ORDER BY deve ser a última cláusula aplicada aos resultados. Por esse motivo, não há tradução de uso geral para esses dois métodos. |
Reverse | A tradução desse método é possível para um conjunto ordenado, mas não é traduzida atualmente pelo LINQ para SQL. |
Last, LastOrDefault | A tradução desses métodos é possível para um conjunto ordenado, mas não é traduzida atualmente pelo LINQ para SQL. |
ElementAt, ElementAtOrDefault | As consultas SQL operam em vários conjuntos, não em sequências indexáveis. |
DefaultIfEmpty (sobrecarga com arg padrão) | Em geral, um valor padrão não pode ser especificado para uma tupla arbitrária. Valores nulos para tuplas são possíveis em alguns casos por meio de junções externas. |
Conversão de expressão
Semântica nula
LINQ to SQL não impõe semântica de comparação nula no SQL. Os operadores de comparação são traduzidos sintaticamente para seus equivalentes sql. Por esse motivo, a semântica reflete a semântica do SQL definida por configurações de conexão ou servidor. Por exemplo, dois valores nulos são considerados desiguais nas configurações padrão do SQL Server, mas você pode alterar as configurações para alterar a semântica. O LINQ to SQL não considera as configurações do servidor quando converte consultas.
Uma comparação com o nulo literal é traduzida para a versão apropriada do SQL (is null
ou is not null
).
O valor de null
na ordenação é definido pelo SQL Server. LINQ to SQL não altera a ordenação.
Agregações
O método de agregação do operador de consulta padrão Sum resulta em zero para uma sequência vazia ou para uma sequência que contém apenas valores nulos. No LINQ to SQL, a semântica do SQL é deixada inalterada e Sum é avaliada null
como em vez de zero para uma sequência vazia ou para uma sequência que contém apenas nulos.
As limitações de SQL em resultados intermediários se aplicam a agregações no LINQ to SQL. O Sum de quantidades inteiras de 32 bits não foi calculada usando resultados de 64 bits. Poderá ocorrer um estouro de uma conversão LINQ to SQL do Sum, mesmo se a implementação do operador de consulta padrão não causar um estouro da sequência correspondente na memória.
Da mesma forma, a tradução LINQ to SQL de Average valores inteiros é computada como um integer
, não como um double
.
Argumentos de entidade
O LINQ to SQL permite que os tipos de entidade sejam usados nos métodos GroupBy e OrderBy. Na tradução desses operadores, o uso de um argumento de um tipo é considerado o equivalente a especificar todos os membros desse tipo. Por exemplo, o código a seguir é 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 equiparáveis e comparáveis
A igualdade de argumentos é necessária na implementação dos seguintes métodos:
O LINQ to SQL dá suporte à igualdade e à comparação de argumentos simples , mas não a argumentos que são ou contêm sequências. Um argumento simples é um tipo que pode ser mapeado para uma linha SQL. Uma projeção de um ou mais tipos de entidade que podem ser determinados estaticamente para não conter uma sequência é considerada um argumento simples.
Veja a seguir exemplos de argumentos simples:
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})
Veja a seguir exemplos de argumentos não simples (hierá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)
Tradução de funções do Visual Basic
As seguintes funções auxiliares usadas pelo compilador do Visual Basic são traduzidas para funções e operadores SQL correspondentes:
CompareString
DateTime.Compare
Decimal.Compare
IIf (in Microsoft.VisualBasic.Interaction)
Métodos de conversão:
ToBoolean
ToSByte
ToByte
ToChar
ToCharArrayRankOne
ToDate
ToDecimal
ToDouble
ToInteger
ToUInteger
ToLong
ToULong
ToShort
ToUShort
ToSingle
ToString
Suporte à herança
Restrições de mapeamento de herança
Para obter mais informações, consulte Como mapear hierarquias de herança.
Herança em consultas
As conversões do C# são suportadas apenas na projeção. Conversões que são usadas em outro lugar não são convertidas e são ignoradas. Além dos nomes de função SQL, o SQL realmente só executa o equivalente do CLR (Common Language Runtime). Convert Ou seja, o SQL pode alterar o valor de um tipo para outro. Não há nenhum equivalente de conversão do CLR porque não há nenhum conceito de reinterpretação dos mesmos bits como os de outro tipo. É por isso que uma conversão em C# funciona apenas localmente. Ela não funciona remotamente.
Os operadores is
e as
o GetType
método não são restritos ao Select
operador. Eles também podem ser usados em outros operadores de consulta.
Suporte ao SQL Server 2008
A partir do .NET Framework 3.5 SP1, o LINQ to SQL dá suporte ao mapeamento para novos tipos de data e hora introduzidos com o SQL Server 2008. Porém, há algumas limitações para os operadores de consulta LINQ to SQL que você pode usar ao operar em relação a valores mapeados para esses novos tipos.
Operadores de consulta sem suporte
Não há suporte para os seguintes operadores de consulta em valores mapeados para os novos tipos de data e hora do SQL Server: DATETIME2
, , DATE
e TIME
DATETIMEOFFSET
.
Aggregate
Average
LastOrDefault
OfType
Sum
Para obter mais informações sobre o mapeamento para esses tipos de data e hora do SQL Server, consulte SQL-CLR Type Mapping.
Suporte ao SQL Server 2005
O LINQ to SQL não dá suporte aos seguintes recursos do SQL Server 2005:
Procedimentos armazenados escritos para SQL CLR.
Tipo definido pelo usuário.
Recursos de consulta XML.
Suporte ao SQL Server 2000
As seguintes limitações do SQL Server 2000 (em comparação com o Microsoft SQL Server 2005) afetam o LINQ ao suporte ao SQL.
Operadores Cross Apply e Outer Apply
Esses operadores não estão disponíveis no SQL Server 2000. LINQ to SQL tenta uma série de regravações para substituí-las por junções apropriadas.
O Cross Apply
e o Outer Apply
são gerados para navegações de relacionamento. O conjunto de consultas para as quais essas reescritas são possíveis não é bem definido. Por esse motivo, o conjunto mínimo de consultas com suporte para o SQL Server 2000 é o conjunto que não envolve navegação de relação.
text/ntext
Os tipos text
/ ntext
de dados não podem ser usados em certas operações de consulta contra varchar(max)
/ nvarchar(max)
, as quais são suportadas pelo Microsoft SQL Server 2005.
Nenhuma resolução está disponível para essa limitação. Especificamente, você não pode usar Distinct()
em qualquer resultado que contenha membros mapeados para as colunas text
ou ntext
.
Comportamento disparado por consultas aninhadas
O associador do SQL Server 2000 (por meio do SP4) tem algumas idiossincrasias que são disparadas por consultas aninhadas. O conjunto de consultas SQL que dispara essas idiossincrasias não está bem definido. Por esse motivo, você não pode definir o conjunto de consultas LINQ to SQL que podem causar exceções do SQL Server.
Operadores Skip e Take
Take e Skip têm certas limitações quando são usadas em consultas no SQL Server 2000. Para obter mais informações, consulte a entrada "Ignorar e aceitar exceções no SQL Server 2000" na solução de problemas.
Materialização de objeto
A materialização cria objetos CLR de linhas retornadas por uma ou mais consultas SQL.
As seguintes chamadas são executadas localmente como parte da materialização:
Construtores
Métodos
ToString
em projeçõesConversões de tipos em projeções
Os métodos que seguem o AsEnumerable método são executados localmente. Esse método não causa a execução imediata.
Você pode usar
struct
como o tipo de retorno de um resultado de consulta ou como um membro do tipo de resultado. As entidades precisam ser classes. Tipos anônimos são materializados como instâncias de classe, mas structs nomeados (não entidades) podem ser usados na projeção.Um membro do tipo do retorno de um resultado de consulta pode ser do tipo IQueryable<T>. É materializado como uma coleção local.
Os métodos a seguir causam a materialização imediata da sequência à qual os métodos são aplicados: