Partilhar via


Tradução do operador de consulta padrão

LINQ to SQL traduz Operadores de Consulta Padrão para comandos SQL. O processador de consultas do banco de dados determina a semântica de execução da tradução SQL.

Os Operadores de Consulta Padrão são definidos em relação a 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).

SQL lida principalmente com conjuntos não ordenados de valores. A ordenação é normalmente uma operação de pós-processamento explicitamente declarada que é aplicada ao resultado final de uma consulta e não aos resultados intermediários. A identidade é definida por valores. Por esse motivo, as consultas SQL são entendidas para lidar com multisets (bags) em vez de conjuntos.

Os parágrafos a seguir descrevem as diferenças entre os Operadores de Consulta Padrão e sua tradução SQL para o provedor do SQL Server para LINQ to SQL.

Suporte ao Operador

Concat

O Concat método é definido para conjuntos ordenados onde a ordem do recetor e a ordem do argumento são as mesmas. Concat funciona como UNION ALL sobre os multisets seguidos pela ordem comum.

A etapa final é ordenar em SQL antes que os resultados sejam produzidos. Concat não preserva a ordem dos seus argumentos. Para garantir o pedido apropriado, você deve solicitar explicitamente os resultados do Concat.

Intersecção, Exceto, União

Os Intersect métodos e Except são bem definidos apenas em sets. A semântica para multiconjuntos é indefinida.

O Union método é definido para multisets como a concatenação não ordenada dos multisets (efetivamente o resultado da cláusula UNION ALL em SQL).

Tomar, Pular

Take e Skip os métodos são bem definidos apenas contra conjuntos ordenados. A semântica para conjuntos não ordenados ou multiconjuntos são indefinidas.

Nota

Take e Skip têm certas limitações quando são usados em consultas no SQL Server 2000. Para obter mais informações, consulte o Entrada "Ignorar e receber exceções no SQL Server 2000" na solução de problemas.

Devido a limitações na ordenação em SQL, 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 ordem 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 todas as ordens especificadas devem ser consistentes quando Take e Skip estão encadeadas. Caso contrário, os resultados são indefinidos.

Ambos Take e Skip são bem definidos para argumentos integrais constantes e 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. A razão mais comum é a diferença entre multiconjuntos não ordenados e sequências.

Operadores Fundamentação
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 esta razão, não existe uma tradução de uso geral para estes dois métodos.
Reverse A tradução deste método é possível para um conjunto ordenado, mas atualmente não é traduzida pelo LINQ para SQL.
Last, LastOrDefault A tradução desses métodos é possível para um conjunto ordenado, mas atualmente não é traduzida 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 através de junções externas.

Tradução de Expressões

Semântica NULL

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 SQL definida pelas configurações de servidor ou conexão. 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 traduz consultas.

Uma comparação com o literal null é convertida para a versão SQL apropriada (is null ou is not null).

O valor de null no agrupamento é definido pelo SQL Server. LINQ to SQL não altera o agrupamento.

Agregados

O método Sum de agregação Standard Query Operator é avaliado como zero para uma sequência vazia ou para uma sequência que contém apenas nulos. No LINQ to SQL, a semântica do SQL é deixada inalterada e Sum é avaliada como null em vez de zero para uma sequência vazia ou para uma sequência que contém apenas nulos.

As limitações do SQL em resultados intermediários aplicam-se a agregações em LINQ to SQL. O Sum de quantidades inteiras de 32 bits não é calculado usando resultados de 64 bits. Pode ocorrer estouro para uma tradução LINQ to SQL do , mesmo que a implementação do Operador de SumConsulta Padrão não cause um estouro para a sequência correspondente na memória.

Da mesma forma, a tradução LINQ to SQL de Average valores inteiros é calculada como um integer, não como um double.

Argumentos da entidade

O LINQ to SQL permite que tipos GroupBy de entidade sejam usados nos métodos 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 Equatable / Comparáveis

A igualdade de argumentos é necessária na implementação dos seguintes métodos:

O LINQ to SQL oferece suporte à igualdade e à comparação para argumentos simples , mas não para 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.

Seguem-se 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})

Seguem-se exemplos de argumentos não planos (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 que são usadas pelo compilador do Visual Basic são convertidas para operadores e funções 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 sucessório

Restrições de mapeamento de herança

Para obter mais informações, consulte Como mapear hierarquias de herança.

Herança em consultas

As versões em C# são suportadas apenas na projeção. Os moldes que são usados em outros lugares não são traduzidos e são ignorados. Além dos nomes de função SQL, o SQL realmente só executa o equivalente ao Common Language Runtime (CLR). Convert Ou seja, o SQL pode alterar o valor de um tipo para outro. Não há equivalente ao CLR cast porque não há nenhum conceito de reinterpretar os mesmos bits que os de outro tipo. É por isso que um elenco em C# funciona apenas localmente. Não é remoto.

Os operadores, is e , e o GetType método não se restringem asao 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 oferece suporte ao mapeamento para novos tipos de data e hora introduzidos com o SQL Server 2008. Mas, 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

Os operadores de consulta a seguir não têm suporte em valores mapeados para os novos tipos de data e hora do SQL Server: DATETIME2, DATE, TIMEe DATETIMEOFFSET.

  • Aggregate

  • Average

  • LastOrDefault

  • OfType

  • Sum

Para obter mais informações sobre como mapear para esses tipos de data e hora do SQL Server, consulte Mapeamento de tipo SQL-CLR.

Suporte ao SQL Server 2005

O LINQ to SQL não oferece 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 suporte ao LINQ to SQL.

Operadores de aplicação cruzada e aplicação externa

Esses operadores não estão disponíveis no SQL Server 2000. O LINQ to SQL tenta uma série de regravações para substituí-las por junções apropriadas.

Cross Apply e Outer Apply são gerados para navegações de relacionamento. O conjunto de consultas para as quais tais regravações são possíveis não está 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 relacionamento.

texto / ntexto

Os tipos text / ntext de dados não podem ser usados em determinadas operações de consulta em relação ao varchar(max) / nvarchar(max), que são suportados pelo Microsoft SQL Server 2005.

Nenhuma resolução está disponível para esta limitação. Especificamente, você não pode usar Distinct() em qualquer resultado que contenha membros mapeados ou text ntext colunas.

Comportamento acionado por consultas aninhadas

O fichário do SQL Server 2000 (até SP4) tem algumas idiossincrasias que são acionadas por consultas aninhadas. O conjunto de consultas SQL que aciona essas idiossincrasias não está bem definido. Por esse motivo, não é possível definir o conjunto de consultas LINQ to SQL que podem causar exceções do SQL Server.

Operadores de Pular e Levar

Take e Skip têm certas limitações quando são usados em consultas no SQL Server 2000. Para obter mais informações, consulte o Entrada "Ignorar e receber exceções no SQL Server 2000" na solução de problemas.

Materialização de Objetos

A materialização cria objetos CLR a partir de linhas que são retornadas por uma ou mais consultas SQL.

  • As seguintes chamadas são executadas localmente como parte da materialização:

    • Construtores

    • ToString Métodos em projeções

    • Tipos de moldes em projeções

  • Os métodos que seguem o AsEnumerable método são executados localmente. Este método não causa execução imediata.

  • Você pode usar a struct como o tipo de retorno de um resultado de consulta ou como um membro do tipo de resultado. As entidades devem ser classes. Tipos anônimos são materializados como instâncias de classe, mas estruturas nomeadas (não-entidades) podem ser usadas na projeção.

  • Um membro do tipo de retorno de um resultado de consulta pode ser do tipo IQueryable<T>. Materializa-se como uma coleção local.

  • Os seguintes métodos causam a materialização imediata da sequência à qual os métodos são aplicados:

Consulte também