Problemas conocidos y consideraciones en LINQ to Entities
En esta sección se ofrece información sobre los problemas conocidos relacionados con las consultas de LINQ to Entities.
Consultas LINQ que no se pueden almacenar en memoria caché
A partir de .NET Framework 4.0.5, las consultas LINQ to Entities se almacenan automáticamente en memoria caché. Sin embargo, as consultas LINQ to Entities que aplican el operador Enumerable.Contains
a colecciones en memoria no se almacenan en memoria caché automáticamente. Tampoco se permite parametrizar colecciones en memoria en consultas LINQ compiladas.
Pérdida de información de ordenación
La proyección de columnas en un tipo anónimo provocará la pérdida de información de ordenación en algunas consultas que se ejecuten en un conjunto de base de datos de SQL Server 2005 con un nivel de compatibilidad de "80". Esto se produce cuando un nombre de columna en la lista ORDER BY coincide con un nombre de columna en el selector, como se muestra en el ejemplo siguiente:
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
Enteros sin signo no admitidos
La especificación de un tipo entero sin signo en una consulta de LINQ to Entities no se admite porque Entity Framework no admite enteros sin signo. Si se especifica un entero sin signo, se producirá una excepción ArgumentException durante la conversión de la expresión de consulta, como se muestra en el ejemplo siguiente. En este ejemplo se consulta un pedido cuyo número de identificación (Id.) es 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
Errores de la conversión de tipos
En Visual Basic, cuando se asigna una propiedad a una columna de tipo bit de SQL Server con un valor de 1 utilizando la función CByte
, se produce una excepción SqlException con el mensaje "Error de desbordamiento aritmético". En el ejemplo siguiente se consulta la columna Product.MakeFlag
en la base de datos de ejemplo AdventureWorks y se produce una excepción cuando tiene lugar una iteración en los resultados de la consulta.
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
Referencia a variables no escalares no admitida
En una consulta no se puede hacer referencia a variables no escalares, tales como una entidad. Cuando este tipo de consulta se ejecuta, se genera una excepción NotSupportedException con un mensaje que indica "No se puede crear un valor constante de tipo EntityType
". Sólo los tipos primitivos ('como Int32, String y Guid') se admiten en este contexto.".
Nota
Permite hacer referencia a una colección de variables escalares.
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
Se puede producir un error en consultas anidadas con SQL Server 2000
Con SQL Server 2000, se puede producir un error en consultas LINQ to Entities si se generan consultas Transact-SQL anidadas con tres o más niveles de profundidad.
Proyectar a un tipo anónimo
Si define su ruta de acceso de consultas inicial para incluir objetos relacionados utilizando el método Include sobre ObjectQuery<T> y, a continuación, utiliza LINQ para proyectar los objetos devueltos sobre un tipo anónimo, los objetos especificados en el método de inclusión no se incluyen en los resultados de la 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 obtener objetos relacionados, no proyecte los tipos devueltos sobre un 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