Partilhar via


Comparações nulas

Um null valor na fonte de dados indica que o valor é desconhecido. Nas consultas LINQ to Entities, você pode verificar se há valores nulos para que determinados cálculos ou comparações sejam executados apenas em linhas que tenham dados válidos ou não nulos. A semântica nula CLR, no entanto, pode diferir da semântica nula da fonte de dados. A maioria dos bancos de dados usa uma versão da lógica de três valores para lidar com comparações nulas. Ou seja, uma comparação com um valor nulo não avalia a true ou false, avalia a unknown. Muitas vezes esta é uma implementação de nulos ANSI, mas nem sempre é o caso.

Por padrão no SQL Server, a comparação null-equals-null retorna um valor nulo. No exemplo a seguir, as linhas onde ShipDate é nulo são excluídas do conjunto de resultados e a instrução Transact-SQL retornaria 0 linhas.

-- Find order details and orders with no ship date.  
SELECT h.SalesOrderID  
FROM Sales.SalesOrderHeader h  
JOIN Sales.SalesOrderDetail o ON o.SalesOrderID = h.SalesOrderID  
WHERE h.ShipDate IS Null  

Isso é muito diferente da semântica nula CLR, onde a comparação null-equals-null retorna true.

A consulta LINQ a seguir é expressa no CLR, mas é executada na fonte de dados. Como não há garantia de que a semântica CLR será honrada na fonte de dados, o comportamento esperado é indeterminado.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    ObjectSet<SalesOrderHeader> orders = context.SalesOrderHeaders;
    ObjectSet<SalesOrderDetail> details = context.SalesOrderDetails;

    var query =
        from order in orders
        join detail in details
        on order.SalesOrderID
        equals detail.SalesOrderID
        where order.ShipDate == null
        select order.SalesOrderID;

    foreach (var OrderID in query)
    {
        Console.WriteLine("OrderID : {0}", OrderID);
    }
}
Using context As New AdventureWorksEntities()

    Dim orders As ObjectSet(Of SalesOrderHeader) = context.SalesOrderHeaders
    Dim details As ObjectSet(Of SalesOrderDetail) = context.SalesOrderDetails

    Dim query = _
        From order In orders _
        Join detail In details _
        On order.SalesOrderID _
        Equals detail.SalesOrderID _
        Where order.ShipDate = Nothing
        Select order.SalesOrderID


    For Each orderID In query
        Console.WriteLine("OrderID: {0} ", orderID)
    Next
End Using

Seletores de chave

Um seletor de chave é uma função usada nos operadores de consulta padrão para extrair uma chave de um elemento. Na função seletora de teclas, uma expressão pode ser comparada com uma constante. A semântica nula CLR é exibida se uma expressão for comparada a uma constante nula ou se duas constantes nulas forem comparadas. A semântica nula de armazenamento é exibida se duas colunas com valores nulos na fonte de dados forem comparadas. Os seletores de chaves são encontrados em muitos dos operadores de consulta padrão de agrupamento e ordenação, como GroupBy, e são usados para selecionar chaves pelas quais ordenar ou agrupar os resultados da consulta.

Propriedade nula em um objeto nulo

No Entity Framework, as propriedades de um objeto nulo são nulas. Quando você tenta fazer referência a uma propriedade de um objeto nulo no CLR, você receberá um NullReferenceExceptionarquivo . Quando uma consulta LINQ envolve uma propriedade de um objeto nulo, isso pode resultar em comportamento inconsistente.

Por exemplo, na consulta a seguir, a conversão para NewProduct é feita na camada de árvore de comandos, o que pode resultar na Introduced propriedade sendo nula. Se o banco de dados definiu comparações nulas de tal forma que a DateTime comparação seja avaliada como verdadeira, a linha será incluída.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{

    DateTime dt = new DateTime();
    var query = context.Products
        .Where(p => (p as NewProduct).Introduced > dt)
        .Select(x => x);
}
Using context As New AdventureWorksEntities()
    Dim dt As DateTime = New DateTime()
    Dim query = context.Products _
        .Where(Function(p) _
            ((DirectCast(p, NewProduct)).Introduced > dt)) _
        .Select(Function(x) x)
End Using

Passando coleções nulas para funções agregadas

No LINQ to Entities, quando você passa uma coleção que suporta IQueryable uma função agregada, as operações de agregação são executadas no banco de dados. Pode haver diferenças nos resultados de uma consulta que foi executada na memória e uma consulta que foi executada no banco de dados. Com uma consulta na memória, se não houver correspondências, a consulta retornará zero. No banco de dados, a mesma consulta retorna null. Se um null valor for passado para uma função de agregação LINQ, uma exceção será lançada. Para aceitar valores possíveis null , converta os tipos e as propriedades dos tipos que recebem resultados de consulta em tipos de valor anuláveis.

Consulte também