次の方法で共有


LINQ to エンティティの既知の問題と考慮事項

このセクションでは、LINQ to Entities クエリに関する既知の問題について説明します。

キャッシュできない LINQ クエリ

.NET Framework 4.5 以降では、LINQ to Entities クエリが自動的にキャッシュされます。 ただし、 Enumerable.Contains 演算子をメモリ内コレクションに適用する LINQ to Entities クエリは、自動的にはキャッシュされません。 また、コンパイル済みの LINQ クエリでのメモリ内コレクションのパラメーター化は許可されません。

注文情報が失われた

列を匿名型に射影すると、互換性レベル "80" に設定された SQL Server 2005 データベースに対して実行される一部のクエリで順序情報が失われます。 これは、次の例に示すように、並べ替えリスト内の列名がセレクターの列名と一致する場合に発生します。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    // Ordering information is lost when executed against a SQL Server 2005
    // database running with a compatibility level of "80".
    var results = context.Contacts.SelectMany(c => c.SalesOrderHeaders)
        .OrderBy(c => c.SalesOrderDetails.Count)
        .Select(c => new { c.SalesOrderDetails.Count });

    foreach (var result in results)
        Console.WriteLine(result.Count);
}
Using context As New AdventureWorksEntities()
    ' Ordering information is lost when executed against a SQL Server 2005
    ' database running with a compatibility level of "80".
    Dim results = context.Contacts.SelectMany(Function(c) c.SalesOrderHeaders) _
        .OrderBy(Function(c) c.SalesOrderDetails.Count) _
        .Select(Function(c) New With {c.SalesOrderDetails.Count})

    For Each result In results
        Console.WriteLine(result.Count)
    Next
End Using

符号なし整数はサポートされていません

ENTITY Framework では符号なし整数がサポートされていないため、LINQ to Entities クエリでの符号なし整数型の指定はサポートされていません。 符号なし整数を指定すると、次の例に示すように、クエリ式の変換中に ArgumentException 例外がスローされます。 この例では、ID 48000 の注文を照会します。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    uint s = UInt32.Parse("48000");

    IQueryable<SalesOrderDetail> query = from sale in context.SalesOrderDetails
                                         where sale.SalesOrderID == s
                                         select sale;

    // NotSupportedException exception is thrown here.
    try
    {
        foreach (SalesOrderDetail order in query)
            Console.WriteLine("SalesOrderID: " + order.SalesOrderID);
    }
    catch (NotSupportedException ex)
    {
        Console.WriteLine($"Exception: {ex.Message}");
    }
}
Using context As New AdventureWorksEntities()
    Dim saleId As UInteger = UInt32.Parse("48000")

    Dim query = _
        From sale In context.SalesOrderDetails _
        Where sale.SalesOrderID = saleId _
        Select sale

    Try
        ' NotSupportedException exception is thrown here.
        For Each order As SalesOrderDetail In query
            Console.WriteLine("SalesOrderID: " & order.SalesOrderID)
        Next
    Catch ex As NotSupportedException
        Console.WriteLine("Exception: " + ex.Message)
    End Try
End Using

型変換エラー

Visual Basic では、プロパティが、 CByte 関数を使用して値 1 の SQL Server ビット型の列にマップされると、"算術オーバーフロー エラー" メッセージを含む SqlException がスローされます。 次の例では、AdventureWorks サンプル データベースの Product.MakeFlag 列に対してクエリを実行します。クエリ結果が反復処理されると例外がスローされます。

Using context As New AdventureWorksEntities()
    Dim productsList = _
        From product In context.Products _
        Select CByte(product.MakeFlag)

    ' Throws an SqlException exception with a "Arithmetic overflow error 
    ' for data type tinyint" message when a value of 1 is iterated over.
    For Each makeFlag In productsList
        Console.WriteLine(makeFlag)
    Next
End Using

サポートされていないスカラー変数の参照

クエリでのエンティティなどの非スカラー変数の参照はサポートされていません。 このようなクエリを実行すると、 NotSupportedException 例外がスローされ、"unable to create a constant value of type EntityType。 このコンテキストでは、プリミティブ型 (Int32、String、Guid など) のみがサポートされています。

スカラー変数のコレクションの参照がサポートされています。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    Contact contact = context.Contacts.FirstOrDefault();

    // Referencing a non-scalar closure in a query will
    // throw an exception when the query is executed.
    IQueryable<string> contacts = from c in context.Contacts
        where c == contact
        select c.LastName;

    try
    {
        foreach (string name in contacts)
        {
            Console.WriteLine($"Name: ");
        }
    }
    catch (NotSupportedException ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Using context As New AdventureWorksEntities()

    Dim contact As Contact = context.Contacts.FirstOrDefault()

    ' Referencing a non-scalar closure in a query will
    ' throw an exception when the query is executed.
    Dim contacts = From c In context.Contacts _
                   Where c.Equals(contact) _
                   Select c.LastName

    Try
        For Each name As String In contacts
            Console.WriteLine("Name: ", name)
        Next

    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try

End Using

入れ子になったクエリが SQL Server 2000 で失敗する可能性がある

SQL Server 2000 では、LINQ to Entities クエリは、3 つ以上のレベルの深い入れ子になった Transact-SQL クエリを生成すると失敗する可能性があります。

匿名型への射影

ObjectQuery<T>Include メソッドを使用して関連オブジェクトを含める最初のクエリ パスを定義し、LINQ を使用して返されたオブジェクトを匿名型に射影する場合、include メソッドで指定されたオブジェクトはクエリ結果に含まれません。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    var resultWithoutRelatedObjects =
        context.Contacts.Include("SalesOrderHeaders").Select(c => new { c }).FirstOrDefault();
    if (resultWithoutRelatedObjects.c.SalesOrderHeaders.Count == 0)
    {
        Console.WriteLine("No orders are included.");
    }
}
Using context As New AdventureWorksEntities()
    Dim resultWithoutRelatedObjects = context.Contacts. _
        Include("SalesOrderHeaders"). _
        Select(Function(c) New With {c}).FirstOrDefault()
    If resultWithoutRelatedObjects.c.SalesOrderHeaders.Count = 0 Then
        Console.WriteLine("No orders are included.")
    End If
End Using

関連するオブジェクトを取得するには、返された型を匿名型に射影しないでください。

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    var resultWithRelatedObjects =
        context.Contacts.Include("SalesOrderHeaders").Select(c => c).FirstOrDefault();
    if (resultWithRelatedObjects.SalesOrderHeaders.Count != 0)
    {
        Console.WriteLine("Orders are included.");
    }
}
Using context As New AdventureWorksEntities()
    Dim resultWithRelatedObjects = context.Contacts. _
        Include("SalesOrderHeaders"). _
        Select(Function(c) c).FirstOrDefault()
    If resultWithRelatedObjects.SalesOrderHeaders.Count <> 0 Then
        Console.WriteLine("Orders are included.")
    End If
End Using

こちらも参照ください