Null 比較
資料來源中的 null
值表示該值未知。 在 LINQ to Entities 查詢中,您可以檢查 null 值,如此一來,特定計算或比較就只會在包含有效或非 null 資料的資料列上執行。 不過,CLR null 語意 (Semantics) 可能與資料來源的 null 語意不同。 大部分的資料庫都使用三值邏輯來處理 null 比較, 換句話說,比較 null 值時並不會取得 true
或 false
,而是會取得 unknown
。 通常,這是 ANSI NULLS 的實作,可是實際情況不一定如此。
根據預設,SQL Server 中 null 等於 null 的比較會傳回 null 值。 在下列範例中,結果集會排除 ShipDate
為 null 的資料列,而 Transact-SQL 陳述式會傳回 0 個資料列。
-- 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
這與 CLR null 語意大不相同,其中 null 等於 null 的比較則是會傳回 true。
下列 LINQ 查詢是以 CLR 表示,但卻在資料來源中執行。 因為無法保證 CLR 語意在資料來源能被接受,預期的行為是不確定的。
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
索引鍵選擇器
「索引鍵選取器」是在標準查詢運算子中所使用的函式,可從元素擷取索引鍵。 在索引鍵選擇器函式中,可以將運算式與常數進行比較。 如果比較運算式與 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 (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
將 Null 集合傳遞至彙總函式
在 LINQ to Entities 中,當您將支援 IQueryable
的集合傳遞至彙總函式時,彙總作業會在資料庫執行。 在記憶體中執行的查詢和在資料庫執行的查詢可能會產生不同的結果。 在記憶體中查詢時,如果沒有相符結果,查詢會傳回零。 同樣的查詢在資料庫中則會傳回 null
。 若將 null
值傳遞至 LINQ 彙總函式,則會擲回例外狀況。 若要接受可能的 null
值,請將接收查詢結果的類型屬性轉換為可為 Null 的實值型別。