Nullvergleiche

Ein null Wert in der Datenquelle gibt an, dass der Wert unbekannt ist. In LINQ to Entities-Abfragen können Sie auf NULL-Werte überprüfen, sodass bestimmte Berechnungen oder Vergleiche nur für Zeilen ausgeführt werden, die gültige oder nicht NULL-Daten aufweisen. Die CLR-Nullsemantik kann sich jedoch von der Nullsemantik der Datenquelle unterscheiden. Die meisten Datenbanken verwenden eine Version der dreiwertigen Logik, um Nullvergleiche zu behandeln. Das heißt, ein Vergleich mit einem NULL-Wert wird nicht zu true oder false ausgewertet, sondern zu unknown. Dies ist häufig eine Implementierung von ANSI-Nullen, aber dies ist nicht immer der Fall.

In SQL Server gibt der Null-Gleich-Null-Vergleich standardmäßig einen Nullwert zurück. Im folgenden Beispiel werden die Zeilen, bei denen ShipDate null ist, vom Resultset ausgeschlossen, und die Transact-SQL-Anweisung würde 0 Zeilen zurückgeben.

-- 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 CLR-Nullsemantik, wobei der Null-Gleich-Null-Vergleich "true" zurückgibt.

Die folgende LINQ-Abfrage wird in der CLR ausgedrückt, wird jedoch in der Datenquelle ausgeführt. Da keine Garantie dafür besteht, dass clR-Semantik an der Datenquelle berücksichtigt wird, ist das erwartete Verhalten unbestimmt.

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

Schlüsselselektoren

Eine Schlüsselauswahl ist eine Funktion, die in den Standardabfrageoperatoren zum Extrahieren eines Schlüssels aus einem Element verwendet wird. In der Tastenauswahlfunktion kann ein Ausdruck mit einer Konstante verglichen werden. CLR-Nullsemantik wird angezeigt, wenn ein Ausdruck mit einer Nullkonstante verglichen wird oder zwei Nullkonstanten verglichen werden. Die Speicher-Null-Semantik wird angezeigt, wenn zwei Spalten mit Nullwerten in der Datenquelle verglichen werden. Schlüsselselektoren werden in vielen der Standard-Abfrageoperatoren für Gruppierung und Sortierreihenfolge verwendet, wie GroupBy, um die Schlüssel auszuwählen, nach denen die Abfrageergebnisse sortiert oder gruppiert werden sollen.

NULL-Eigenschaft eines NULL-Objekts

Im Entity Framework sind die Eigenschaften eines NULL-Objekts null. Wenn Sie versuchen, auf eine Eigenschaft eines NULL-Objekts in der CLR zu verweisen, erhalten Sie eine NullReferenceException. Wenn eine LINQ-Abfrage eine Eigenschaft eines NULL-Objekts umfasst, kann dies zu inkonsistenten 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 die Datenbank NULL-Vergleiche definiert hat, sodass der DateTime Vergleich als wahr ausgewertet wird, wird die Zeile einbezogen.

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

Übergeben von NULL-Auflistungen an Aggregatfunktionen

In LINQ to Entities führen Sie eine Sammlung, die IQueryable unterstützt, einer Aggregatfunktion zu, dann werden die Aggregatvorgänge in der Datenbank ausgeführt. Es kann Unterschiede in den Ergebnissen einer Abfrage geben, die im Arbeitsspeicher ausgeführt wurde, und einer Abfrage, die an der Datenbank ausgeführt wurde. Bei einer In-Memory-Abfrage wird bei fehlender Übereinstimmung null zurückgegeben. In der Datenbank gibt die gleiche Abfrage zurück null. Wenn ein null Wert an eine LINQ-Aggregatfunktion übergeben wird, wird eine Ausnahme ausgelöst. Um mögliche null Werte zu akzeptieren, wandeln Sie die Typen und eigenschaften der Typen, die Abfrageergebnisse empfangen, in Nullwertetypen um.

Siehe auch