null數據源中的值表示值未知。 在 LINQ to Entities 查詢中,您可以檢查 Null 值,讓某些計算或比較只會在具有有效或非 Null 數據的數據列上執行。 不過,CLR Null 語意可能與數據源的 Null 語意不同。 大部分的資料庫會使用某種三值邏輯來處理 Null 比對。 也就是說,與 Null 值的比較不會評估為 true 或 false,它會評估為 unknown。 這通常是 ANSI Null 的實作,但情況不一定如此。
根據預設,SQL Server 中的 null-equals-null 比較會傳回 Null 值。 在下列範例中,會從結果集中排除 null 的數據列 ShipDate ,而 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-equals-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 : {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
將空集合傳遞至聚合函數
在 LINQ to Entities 中,當您將支援 IQueryable 的集合傳遞至聚合函數時,匯總作業會在資料庫中執行。 在記憶體中執行的查詢結果和在資料庫中執行的查詢結果可能會有差異。 使用記憶體內部查詢時,如果沒有相符項目,查詢會傳回零。 在資料庫中,相同的查詢會傳 null回 。 如果值 null 傳遞至 LINQ 聚合函數,則會擲回例外狀況。 若要接受可能的 null 值,請將接收查詢結果的類型及其屬性的實值型別轉換成可為 Null 的類型。