Problemas conocidos y consideraciones en LINQ to Entities
En esta sección se ofrece información sobre los problemas conocidos relacionados con consultas de LINQ to Entities .
Pérdida de información de ordenación
Enteros sin signo no admitidos
Errores de la conversión de tipos
Referencia a variables no escalares no admitida
Se puede producir un error en consultas anidadas con SQL Server 2000
Proyectar a un tipo anónimo
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 la 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 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
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);
}
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 se 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 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
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);
}
}
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". Solo 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 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
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);
}
}
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 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 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 resultWithoutRelatedObjects =
context.Contacts.Include("SalesOrderHeaders").Select(c => new { c }).FirstOrDefault();
if (resultWithoutRelatedObjects.c.SalesOrderHeaders.Count == 0)
{
Console.WriteLine("No orders are included.");
}
}
Para obtener objetos relacionados, no proyecte los tipos devueltos sobre un tipo anónimo.
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
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.");
}
}