Dela via


Null-jämförelser

Ett null värde i datakällan anger att värdet är okänt. I LINQ till entitetsfrågor kan du söka efter nullvärden så att vissa beräkningar eller jämförelser endast utförs på rader som har giltiga eller icke-null-data. CLR null-semantik kan dock skilja sig från datakällans null-semantik. De flesta databaser använder en version av trevärdeslogik för att hantera nulljämförelser. En jämförelse mot ett null-värde utvärderas alltså inte till true eller false, den utvärderas till unknown. Detta är ofta en implementering av ANSI-nullvärden, men så är inte alltid fallet.

Som standard i SQL Server returnerar jämförelsen null-equals-null ett null-värde. I följande exempel undantas raderna där ShipDate är null från resultatuppsättningen och Transact-SQL-instruktionen returnerar 0 rader.

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

Detta skiljer sig mycket från CLR null-semantiken, där jämförelsen null-equals-null returnerar sant.

Följande LINQ-fråga uttrycks i CLR, men den körs i datakällan. Eftersom det inte finns någon garanti för att CLR-semantik kommer att respekteras vid datakällan är det förväntade beteendet obestämt.

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

Nyckelväljare

En nyckelväljare är en funktion som används i standardfrågeoperatorerna för att extrahera en nyckel från ett element. I nyckelväljarens funktion kan ett uttryck jämföras med en konstant. CLR null-semantik visas om ett uttryck jämförs med en null-konstant eller om två null-konstanter jämförs. Lagra null-semantik visas om två kolumner med null-värden i datakällan jämförs. Nyckelväljare finns i många av de grupperings- och ordningsföljdsoperatorer för vanliga frågor, till exempel GroupBy, och används för att välja nycklar som frågeresultaten ska sorteras efter eller grupperas efter.

Null-egenskap för ett Null-objekt

I Entity Framework är egenskaperna för ett null-objekt null. När du försöker referera till en egenskap för ett null-objekt i CLR får du en NullReferenceException. När en LINQ-fråga omfattar en egenskap för ett null-objekt kan detta resultera i inkonsekvent beteende.

I följande fråga görs till exempel casten till i kommandoträdlagret, vilket kan leda till NewProduct Introduced att egenskapen blir null. Om databasen har definierat nulljämförelser så att jämförelsen DateTime utvärderas till true inkluderas raden.

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

Skicka Null-samlingar till aggregerade funktioner

I LINQ till entiteter utförs aggregerade åtgärder i databasen när du skickar en samling som stöder IQueryable till en aggregeringsfunktion. Det kan finnas skillnader i resultatet av en fråga som utfördes i minnet och en fråga som utfördes i databasen. Med en minnesintern fråga returnerar frågan noll om det inte finns några matchningar. I databasen returnerar nullsamma fråga . Om ett null värde skickas till en LINQ-mängdfunktion genereras ett undantag. Om du vill acceptera möjliga null värden omvandlar du typerna och egenskaperna för de typer som tar emot frågeresultat till nullbara värdetyper.

Se även