LINQ to Entities 查询转换为命令树并执行后,查询结果通常返回为下列项之一:
概念模型中零个或多个类型化实体对象的集合或复杂类型的投影。
概念模型支持的 CLR 类型。
内联集合。
匿名类型。
对数据源执行查询后,结果将具体化为 CLR 类型,并返回到客户端。 所有对象具体化都由 Entity Framework 执行。 由于无法在实体框架和 CLR 之间进行映射而导致的任何错误,都会在对象实体化的过程中抛出异常。
如果查询执行返回基元概念模型类型,则结果由独立且与实体框架断开连接的 CLR 类型组成。 但是,如果查询返回类型化实体对象的集合, ObjectQuery<T>则这些类型由对象上下文跟踪。 实体框架中定义所有对象行为(例如子/父集合、更改跟踪、多态性等)。 此功能可以在其功能范围内使用,如 Entity Framework 中定义。 有关详细信息,请参阅使用对象。
从查询返回的结构类型(如匿名类型和可为 null 的复杂类型)可以是 null 值。 返回的实体的一个EntityCollection<TEntity>属性也可以是一个null值。 这可能会导致投影具有null值的实体的集合属性,例如在没有元素的FirstOrDefault上调用ObjectQuery<T>。
在某些情况下,查询可能会在执行过程中生成具体化结果,但查询将在服务器上执行,并且实体对象永远不会在 CLR 中具体化。 如果依赖于对象实体化的副作用,这可能会导致问题。
以下示例包含一个自定义类MyContact,该类具有LastName属性。 设置LastName属性时,count变量会增加。 如果执行以下两个查询,则第一个查询将递增,而第二个查询不会递增 count 。 这是因为在第二个查询中,属性 LastName 从结果中投射出来,并且类 MyContact 从未被创建,因为在存储中执行查询并不需要它。
public static int count = 0;
static void Main(string[] args)
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
var query1 = AWEntities
.Contacts
.Where(c => c.LastName == "Jones")
.Select(c => new MyContact { LastName = c.LastName });
// Execute the first query and print the count.
query1.ToList();
Console.WriteLine("Count: " + count);
//Reset the count variable.
count = 0;
var query2 = AWEntities
.Contacts
.Where(c => c.LastName == "Jones")
.Select(c => new MyContact { LastName = c.LastName })
.Select(my => my.LastName);
// Execute the second query and print the count.
query2.ToList();
Console.WriteLine("Count: " + count);
}
Console.WriteLine("Hit enter...");
Console.Read();
}
Public count As Integer = 0
Sub Main()
Using AWEntities As New AdventureWorksEntities()
Dim query1 = AWEntities.Contacts _
.Where(Function(c) c.LastName = "Jones") _
.Select(Function(c) New MyContact With {.LastName = c.LastName})
' Execute the first query and print the count.
query1.ToList()
Console.WriteLine("Count: " & count)
' Reset the count variable.
count = 0
Dim query2 = AWEntities _
.Contacts() _
.Where(Function(c) c.LastName = "Jones") _
.Select(Function(c) New MyContact With {.LastName = c.LastName}) _
.Select(Function(x) x.LastName)
' Execute the second query and print the count.
query2.ToList()
Console.WriteLine("Count: " & count)
End Using
End Sub
public class MyContact
{
String _lastName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
count++;
}
}
}
Public Class MyContact
Private _lastName As String
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
count += 1
End Set
End Property
End Class