Porównania wartości Null
null
Wartość w źródle danych wskazuje, że wartość jest nieznana. W zapytaniach LINQ to Entities można sprawdzić wartości null, aby niektóre obliczenia lub porównania były wykonywane tylko w wierszach, które mają prawidłowe lub inne niż null, dane. Semantyka wartości null clR może jednak różnić się od semantyki null źródła danych. Większość baz danych używa wersji trzywartościowej logiki do obsługi porównań o wartości null. Oznacza to, że porównanie z wartością null nie daje wartości lub true
false
, które daje wartość unknown
. Często jest to implementacja wartości null ANSI, ale nie zawsze tak jest.
Domyślnie w programie SQL Server porównanie null-equals-null zwraca wartość null. W poniższym przykładzie wiersze, w których ShipDate
wartość null jest wykluczona z zestawu wyników, a instrukcja Transact-SQL zwróci 0 wierszy.
-- 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
Różni się to zupełnie od semantyki null CLR, gdzie porównanie null-equals-null zwraca wartość true.
Następujące zapytanie LINQ jest wyrażone w clR, ale jest wykonywane w źródle danych. Ponieważ nie ma gwarancji, że semantyka CLR będzie honorowana w źródle danych, oczekiwane zachowanie jest nieokreślone.
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
Selektory kluczy
Selektor kluczy to funkcja używana w standardowych operatorach zapytań do wyodrębniania klucza z elementu. W funkcji selektora kluczy wyrażenie można porównać ze stałą. Semantyka wartości null CLR jest wystawiana, jeśli wyrażenie jest porównywane z stałą null lub jeśli są porównywane dwie stałe null. Semantyka przechowywania wartości null jest pokazywana, jeśli są porównywane dwie kolumny z wartościami null w źródle danych. Selektory kluczy znajdują się w wielu operatorach grupowania i porządkowania standardowych operatorów zapytań, takich jak GroupBy, i służą do wybierania kluczy, według których należy porządkować lub grupować wyniki zapytania.
Właściwość Null w obiekcie null
W programie Entity Framework właściwości obiektu o wartości null mają wartość null. Podczas próby odwołania do właściwości obiektu o wartości null w clR zostanie wyświetlony element NullReferenceException. Gdy zapytanie LINQ obejmuje właściwość obiektu o wartości null, może to spowodować niespójne zachowanie.
Na przykład w poniższym zapytaniu rzutowanie do NewProduct
jest wykonywane w warstwie drzewa poleceń, co może spowodować Introduced
, że właściwość ma wartość null. Jeśli w bazie danych zdefiniowano porównania o wartości null, takie jak DateTime porównanie daje wartość true, wiersz zostanie uwzględniony.
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
Przekazywanie kolekcji null do funkcji agregujących
W przypadku przekazywania kolekcji obsługującej IQueryable
funkcję agregacji linQ to Entities operacje agregacji są wykonywane w bazie danych. Mogą istnieć różnice w wynikach zapytania, które zostało wykonane w pamięci i zapytaniu, które zostało wykonane w bazie danych. W przypadku zapytania w pamięci, jeśli nie ma dopasowań, zapytanie zwraca zero. W bazie danych to samo zapytanie zwraca wartość null
. null
Jeśli wartość zostanie przekazana do funkcji agregującej LINQ, zostanie zgłoszony wyjątek. Aby zaakceptować możliwe null
wartości, rzutuj typy i właściwości typów, które odbierają wyniki zapytania do typów wartości dopuszczających wartość null.