Problemas conhecidos e considerações no LINQ to Entities
Esta seção fornece informações sobre problemas conhecidos com consultas do LINQ to Entities.
Consultas LINQ que não podem ser armazenadas em cache
A partir do .NET Framework 4.5, as consultas LINQ to Entities são automaticamente armazenadas em cache. No entanto, as consultas LINQ to Entities que aplicam o operador Enumerable.Contains
a coleções na memória não são armazenadas em cache automaticamente. Além disso, não é permitido parametrizar coleções na memória em consultas LINQ compiladas.
Informações de ordenação perdidas
Projetar colunas em um tipo anônimo fará com que as informações de ordenação sejam perdidas em algumas consultas executadas em um banco de dados SQL Server 2005 definido com um nível de compatibilidade de “80". Isso ocorre quando um nome de coluna na lista order-by corresponde a um nome de coluna no seletor, conforme mostrado no exemplo a seguir:
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
Inteiros sem sinal não suportados
Não há suporte para especificar um tipo inteiro sem sinal em uma consulta LINQ to Entities porque o Entity Framework não dá suporte a inteiros não assinados. Se você especificar um inteiro não assinado, será gerada uma exceção ArgumentException durante a tradução da expressão de consulta, conforme mostrado no exemplo a seguir. Este exemplo consulta um pedido com a 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
Erros de conversão de tipos
No Visual Basic, quando uma propriedade é mapeada para uma coluna de tipo bit do SQL Server com um valor igual a 1 usando a função CByte
, um SqlException é gerado com uma mensagem de “Erro de estouro aritmético". O exemplo a seguir consulta a coluna Product.MakeFlag
no banco de dados de exemplo AdventureWorks e uma exceção é gerada quando os resultados da consulta são iterados sobre.
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
Referenciando variáveis não escalares não suportadas
A referência a variáveis não escalares, como uma entidade, em uma consulta não é suportada. Quando uma consulta desse tipo é executada, é gerada uma exceção NotSupportedException com a mensagem "Não foi possível criar um valor constante de tipo EntityType
. Apenas tipos primitivos ('como Int32, String e GUID') são suportados nesse contexto."
Observação
A referência a uma coleção de variáveis escalares é suportada.
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
Pode haver falha em consultas aninhadas com o SQL Server 2000
Com o SQL Server 2000, pode haver falha em consultas do LINQ to Entities se elas gerarem consultas Transact-SQL aninhadas com três ou mais níveis de profundidade.
Projetando para um tipo anônimo
Se você definir o caminho da consulta inicial para incluir objetos relacionados usando o método Include no ObjectQuery<T> e, em seguida, usar o LINQ para projetar os objetos retornados para um tipo anônimo, os objetos especificados no método de inclusão não serão incluídos nos resultados da consulta.
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
Para obter objetos relacionados, não projete tipos retornados para um tipo anônimo.
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