NULL-Vergleiche

Ein NULL-Wert in der Datenquelle gibt an, dass der Wert unbekannt ist. Sie können in LINQ to Entities -Abfragen auf NULL-Werte überprüfen, damit bestimmte Berechnungen oder Vergleiche nur für Zeilen mit gültigen Daten bzw. Daten, die nicht den Wert NULL haben, ausgeführt werden. Die NULL-Semantik der CLR unterscheidet sich jedoch möglicherweise von der NULL-Semantik der Datenquelle. Die meisten Datenbanken verwenden eine Logikversion mit einer dritten Möglichkeit der Auswertung, um NULL-Vergleiche zu behandeln. Dabei wird jeder Vergleich mit einem NULL-Wert nicht als true oder false, sondern als unknown ausgewertet. Oft ist dies eine Implementierung von ANSI-Nullen, das ist jedoch nicht immer der Fall.

Standardmäßig gibt der NULL-gleich-NULL-Vergleich in SQL Server einen NULL-Wert zurück. Im folgenden Beispiel werden die Zeilen, in denen ShipDate gleich NULL ist, vom Resultset ausgeschlossen, sodass die Transact-SQL -Anweisung keine Zeilen zurückgeben würde.

-- 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  

Dies unterscheidet sich sehr von der NULL-Semantik der CLR, bei der der NULL-gleich-NULL-Vergleich true zurückgibt.

Die folgende LINQ-Abfrage wird in der Semantik der CLR ausgedrückt, wird jedoch in der Datenquelle ausgeführt. Da nicht gewährleistet ist, dass die CLR-Semantik von der Datenquelle verarbeitet wird, ist unklar, ob sie sich wie erwartet verhält.

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
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);
    }
}

Schlüsselauswahlfunktionen

Eine Schlüsselauswahl ist eine in den Standardabfrageoperatoren verwendete Funktion zur Extrahierung eines Schlüssels aus einem Element. In der Schlüsselauswahlfunktion kann ein Ausdruck mit einer Konstante verglichen werden. Die NULL-Semantik der CLR wird angewendet, wenn ein Ausdruck mit einer NULL-Konstante oder zwei NULL-Konstanten miteinander verglichen werden. Die NULL-Semantik des Speichers gilt, wenn zwei Spalten mit NULL-Werten in der Datenquelle verglichen werden. Schlüsselauswahlfunktionen sind in vielen der Standardabfrageoperatoren zum Gruppieren und Sortieren zu finden, wie beispielsweise in GroupBy. Sie werden verwendet, um Schlüssel auszuwählen, nach denen die Abfrageergebnisse sortiert oder gruppiert werden sollen.

NULL-Eigenschaft eines NULL-Objekts

In Entity Framework sind die Eigenschaften eines NULL-Objekts gleich NULL. Wenn Sie versuchen, in der CLR auf eine Eigenschaft eines NULL-Objekts zu verweisen, erhalten Sie eine NullReferenceException. Wenn eine LINQ-Abfrage eine Eigenschaft eines NULL-Objekts einschließt, kann dies zu inkonsistentem Verhalten führen.

In der folgenden Abfrage wird die Umwandlung in NewProduct auf der Ebene der Befehlsstruktur durchgeführt. Das kann dazu führen, dass die Introduced-Eigenschaft NULL sein kann. Wenn NULL-Vergleiche in der Datenbank in der Weise definiert wurden, dass der DateTime-Vergleich zu true ausgewertet wird, wird die Zeile eingeschlossen.

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
using (AdventureWorksEntities context = new AdventureWorksEntities())
{

    DateTime dt = new DateTime();
    var query = context.Products
        .Where(p => (p as NewProduct).Introduced > dt)
        .Select(x => x);
}

Übergeben von NULL-Auflistungen an Aggregatfunktionen

In LINQ to Entities werden beim Übergeben einer Auflistung, die IQueryable für eine Aggregatfunktion unterstützt, aggregierte Operationen in der Datenbank ausgeführt. Zwischen den Ergebnissen einer Abfrage, die im Arbeitsspeicher ausgeführt wurde, und einer Abfrage, die in der Datenbank ausgeführt wurde, können Unterschiede bestehen. Bei einer Abfrage im Arbeitsspeicher gibt die Abfrage 0 (null) zurück, wenn keine Übereinstimmungen gefunden werden kann. Bei der Datenbankabfrage gibt die gleiche Abfrage NULL zurück. Wird ein NULL-Wert an eine LINQ-Aggregatfunktion übergeben, wird eine Ausnahme ausgelöst. Wandeln Sie die Typen und die Eigenschaften der Typen, die Abfrageergebnisse empfangen, in NULL-Werte um, um mögliche NULL-Werte zu akzeptieren.

Siehe auch

Konzepte

Ausdrücke in LINQ to Entities-Abfragen