Share via


NULL 比較

データ ソースの null 値は不明な値を表します。 LINQ to Entities クエリでは、null 値をチェックして、必ず null でない有効なデータを持つ行に特定の計算または比較を行うようにすることができます。 ただし、CLR の NULL セマンティクスは、データ ソースの NULL セマンティクスとは異なる場合があります。 ほとんどのデータベースでは、3 値論理を使用して NULL 比較を処理します。 つまり、null 値との比較は true にも false にも評価されず、unknown に評価されます。 これは、多くの場合は ANSI NULL の実装ですが、そうでない場合もあります。

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  

これは、NULL = NULL の比較が true を返す CLR の NULL セマンティクスとは大きく異なります。

次の 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 定数と比較される場合、または 2 つの NULL 定数が比較される場合、CLR の NULL セマンティクスが使用されます。 データ ソースの NULL 値を持つ 2 つの列が比較される場合は、ストア NULL セマンティクスが使用されます。 キー セレクターは、GroupBy など、グループ化や並べ替えの標準クエリ演算子で使用される場合が多く、クエリ結果の並べ替えやグループ化に使用するキーを選択できます。

NULL オブジェクトの NULL プロパティ

Entity Framework では、null オブジェクトのプロパティは null です。 CLR で NULL オブジェクトのプロパティを参照しようとすると、NullReferenceException が返されます。 LINQ クエリに NULL オブジェクトのプロパティが含まれている場合、動作の一貫性が失われることがあります。

たとえば、次のクエリでは、NewProduct へのキャストはコマンド ツリー レイヤーで行われ、Introduced プロパティが NULL になる可能性があります。 DateTime の比較が true に評価されるように NULL 比較がデータベースで定義されている場合に、その行が含められます。

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 をサポートするコレクションを集計関数に渡すと、データベースで集計演算が実行されます。 メモリで実行されたクエリとデータベースで実行されたクエリの結果は、異なる可能性があります。 メモリ内のクエリでは、一致するものがなければ 0 が返されます。 データベースでは、これと同じクエリから null が返されます。 null 値が LINQ 集計関数に渡されると、例外がスローされます。 null 値を受け入れるには、型、およびクエリ結果を受け取るその型のプロパティを Null 許容値型にキャストします。

関連項目