Udostępnij za pośrednictwem


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 truefalse, 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.

Zobacz też