Null 比較

資料來源中的 null 值表示該值未知。在 LINQ to Entities 查詢中,您可以檢查 null 值,以便讓某些計算或比較只會在包含有效或非 null 資料的資料列上執行。不過,CLR null 語意 (Semantics) 可能與資料來源的 null 語意不同。大部分的資料庫都使用三值邏輯來處理 null 比較,也就是對 null 值的比較並不會評估為 truefalse,而是會評估為 unknown。通常,這是 ANSI NULLS 的實作,可是實際情況不一定如此。

根據預設,SQL Server 中 null 等於 null 的比較會傳回 null 值。在下列範例中,會從結果集 (Result Set) 排除 Region 為 null 的資料列,而 Transact-SQL 陳述式 (Statement) 將傳回 0 個資料列。

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

這與 CLR null 語意大不相同,其中 null 等於 null 的比較則是會傳回 true。

下列 LINQ 查詢是以 CLR 表示,但卻在資料來源中執行。因為無法保證 CLR 語意在資料來源能被接受,預期的行為是不確定的。

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

索引鍵選擇器

索引鍵選擇器」(Key Selector) 是標準查詢運算子中使用的函式,用來從項目擷取索引鍵。在索引鍵選擇器函式中,可以將運算式與常數進行比較。如果比較運算式與 null 常數,或比較兩個 null 常數,則會顯示 CLR null 語意。如果比較資料來源中兩個具有 null 值的資料行,則會顯示存放區 null 語意。索引鍵選擇器存在於許多群組和排序的標準查詢運算子 (如 GroupBy),而且是用來選取做為排序或群組依據的索引鍵。

Null 物件上的 Null 屬性

在 Entity Framework 中,null 物件的屬性是 null。當您嘗試參考 CLR 中 null 物件的屬性時,將會收到 NullReferenceException。當 LINQ 查詢包含 null 物件的屬性時,可能會產生不一致的行為。

舉例來說,下列查詢中 NewProduct 的轉型會在命令樹層完成,這可能導致 Introduced 屬性為 null。如果資料庫已定義 null 比較而使 DateTime 的比較評估為 true,則會包含資料列。

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

另請參閱

概念

LINQ to Entities 查詢中的運算式