Znane problemy i zagadnienia dotyczące składnika LINQ to Entities
Ta sekcja zawiera informacje o znanych problemach z zapytaniami LINQ to Entities.
Zapytania LINQ, których nie można buforować
Począwszy od programu .NET Framework 4.5, zapytania LINQ to Entities są automatycznie buforowane. Jednak zapytania LINQ to Entities, które stosują Enumerable.Contains
operator do kolekcji w pamięci, nie są automatycznie buforowane. Ponadto parametryzacja kolekcji w pamięci w skompilowanych zapytaniach LINQ nie jest dozwolona.
Utracono informacje dotyczące zamawiania
Rzutowanie kolumn w typ anonimowy spowoduje utratę informacji o kolejności w niektórych zapytaniach wykonywanych względem bazy danych programu SQL Server 2005 ustawionego na poziom zgodności "80". Dzieje się tak, gdy nazwa kolumny na liście order-by pasuje do nazwy kolumny w selektorze, jak pokazano w poniższym przykładzie:
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
Niepodpisane liczby całkowite nieobsługiwane
Określanie typu niepodpisanej liczby całkowitej w zapytaniu LINQ to Entities nie jest obsługiwane, ponieważ platforma Entity Framework nie obsługuje niepodpisanych liczb całkowitych. Jeśli określisz niepodpisaną liczbę całkowitą, ArgumentException podczas tłumaczenia wyrażenia zapytania zostanie zgłoszony wyjątek, jak pokazano w poniższym przykładzie. W tym przykładzie zapytania dotyczące zamówienia o identyfikatorze 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
Błędy konwersji typów
W języku Visual Basic, gdy właściwość jest mapowana na kolumnę typu bitowego programu SQL Server o wartości 1 przy użyciu CByte
funkcji, SqlException jest zgłaszany komunikat "Błąd przepełnienia arytmetycznego". Poniższy przykład wykonuje zapytanie względem Product.MakeFlag
kolumny w przykładowej bazie danych AdventureWorks i zgłasza wyjątek, gdy wyniki zapytania są iterowane.
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
Odwoływanie się do zmiennych nieskalowych nieobsługiwanych
Odwoływanie się do zmiennych innych niż skalarne, takich jak jednostka, w zapytaniu nie jest obsługiwane. Gdy takie zapytanie zostanie wykonane, NotSupportedException zostanie zgłoszony wyjątek z komunikatem "Nie można utworzyć stałej wartości typu EntityType
. W tym kontekście są obsługiwane tylko typy pierwotne (takie jak Int32, String i Guid').
Uwaga
Odwoływanie się do kolekcji zmiennych skalarnych jest obsługiwane.
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
Zapytania zagnieżdżone mogą zakończyć się niepowodzeniem z programem SQL Server 2000
W przypadku programu SQL Server 2000 zapytania LINQ to Entities mogą zakończyć się niepowodzeniem, jeśli generują zagnieżdżone zapytania języka Transact-SQL, które mają co najmniej trzy poziomy głębiej.
Rzutowanie do typu anonimowego
Jeśli zdefiniujesz początkową ścieżkę zapytania, aby uwzględnić powiązane obiekty przy użyciu metody w ObjectQuery<T> obiekcie , a następnie użyjesz Include linQ do projekcji zwracanych obiektów do typu anonimowego, obiekty określone w metodzie include nie zostaną uwzględnione w wynikach zapytania.
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
Aby uzyskać powiązane obiekty, nie projektuj zwracanych typów do typu anonimowego.
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