LINQ to Entities 中的已知問題和考量

本節提供有關 LINQ to Entities 查詢已知問題的資訊。

不能快取的 LINQ 查詢

從 .NET Framework 4.5 開始會自動快取 LINQ to Entities 查詢。 不過,不會自動快取將 Enumerable.Contains運算子套用至記憶體中集合的 LINQ to Entities 查詢。 此外也不允許在已編譯的 LINQ 查詢中參數化記憶體中的集合。

排序資訊遺失

在針對相容性層級設定為 "80" 的 SQL Server 2005 資料庫執行的某些查詢中,將資料行投影到匿名型別將會造成排序資訊遺失。 如果 order-by 清單中的資料行名稱與 selector 中的資料行名稱相符,就會發生這種情況,如以下範例所示:

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

不支援不帶正負號的整數

不支援在 LINQ to Entities 查詢中指定不帶正負號的整數型別,因為 Entity Framework 不支援不帶正負號的整數。 如果指定不帶正負號的整數,查詢運算式轉譯期間將會擲回 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: {0}", 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 例外狀況,並且顯示一則訊息,表示「無法建立 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: ", 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 查詢產生三層或更多層深度的巢狀 Transact-SQL 查詢,則查詢可能會失敗。

投影至匿名型別

如果您透過在 Include 上使用 ObjectQuery<T> 方法,將初始查詢路徑定義為包括相關物件,然後使用 LINQ 將傳回的物件投影至匿名型別,則包括方法中所指定的物件不會包括在查詢結果中。

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

另請參閱