Sdílet prostřednictvím


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 "Region" gleich NULL ist, vom Resultset ausgeschlossen, sodass die Transact-SQL-Anweisung keine Zeilen zurückgeben würde.

-- Find orders and customers with no regions.
SELECT a.[CustomerID] 
FROM [Northwind].[dbo].[Customers] a
JOIN [Northwind].[dbo].[Orders] b ON a.Region = b.ShipRegion
WHERE a.Region 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 NwEntities As New NorthwindEntities()
    Dim customers As ObjectQuery(Of Customers) = NwEntities.Customers
    Dim orders As ObjectQuery(Of Orders) = NwEntities.Orders

    Dim query = _
        From c In customers _
        Join o In orders On c.Region Equals o.ShipRegion _
        Where c.Region = Nothing _
        Select c.CustomerID

    For Each customerID In query
        Console.WriteLine("Customer ID: ", customerID)
    Next
End Using
using (NorthwindEntities NwEntities = new NorthwindEntities())
{
    ObjectQuery<Customers> customers = NwEntities.Customers;
    ObjectQuery<Orders> orders = NwEntities.Orders;

    IQueryable<string> query = from c in customers
                                  join o in orders on c.Region equals o.ShipRegion
                                  where c.Region == null
                                  select c.CustomerID;

    foreach (string customerID in query)
    {
        Console.WriteLine("Customer ID: {0}", customerID);
    }
}

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 AWEntities As New AdventureWorksEntities()
    Dim dt As DateTime = New DateTime()
    Dim query = AWEntities.Product _
        .Where(Function(p) _
            ((DirectCast(p, NewProduct)).Introduced > dt)) _
        .Select(Function(x) x)
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{

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

Siehe auch

Konzepte

Ausdrücke in LINQ to Entities-Abfragen