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.