本部分提供有关 LINQ to Entities 查询的已知问题的信息。
无法缓存的 LINQ 查询
从 .NET Framework 4.5 开始,LINQ to Entities 查询会自动缓存。 然而,应用Enumerable.Contains运算符于内存集合的LINQ to Entities查询不会被自动缓存。 不允许在编译的 LINQ 查询中参数化内存中集合。
订单信息丢失
将列投影到匿名类型中会导致在针对兼容性级别设置为“80”的 SQL Server 2005 数据库执行的一些查询中丢失排序信息。 当按顺序列表的列名与选择器中的列名匹配时,将发生这种情况,如以下示例所示:
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: {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: ");
}
}
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 将返回的对象投影到匿名类型,那么在 include 方法中指定的对象将不会包含在查询结果中。
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