Query Results
After a LINQ to Entities query is converted to command trees and executed, the query results are usually returned as one of the following:
A collection of zero or more typed entity objects or a projection of complex types in the EDM.
CLR types supported by the EDM.
Inline collections.
Anonymous types.
When the query has executed against the data source, the results are materialized into CLR types and returned to the client. All object materialization is performed by the Entity Framework. Any errors that result from an inability to map between the Entity Framework and the CLR will cause exceptions to be thrown during object materialization.
If the query execution returns primitive EDM types, the results consist of CLR types that are stand-alone and disconnected from the Entity Framework. However, if the query returns a collection of typed entity objects, represented by ObjectQuery, those types are tracked by the object context. All object behavior (such as child/parent collections, change tracking, polymorphism, and so on) are as defined in the Entity Framework. This functionality can be used in its capacity, as defined in the Entity Framework. For more information, see Object Services Overview (Entity Framework).
Struct types returned from queries (such as anonymous types and nullable complex types) can be of null value. An EntityCollection property of a returned entity can also be of null value. This can result from projecting the collection property of an entity that is of null value, such as calling FirstOrDefault on an ObjectQuery that has no elements.
In certain situations, a query might appear to generate a materialized result during its execution, but the query will be executed on the server and the entity object will never be materialized in the CLR. This can cause problems if you are depending on side effects of object materialization.
The following example contains a custom class, MyContact
, with a LastName
property. When the LastName
property is set, a count
variable is incremented. If you execute the two following queries, the first query will increment count
while the second query will not. This is because in the second query the LastName
property is projected from the results and the MyContact
class is never created, because it is not required to execute the query on the store.
Public count As Integer = 0
Sub Main()
Using AWEntities As New AdventureWorksEntities()
Dim query1 = AWEntities.Contact _
.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 _
.Contact() _
.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 static int count = 0;
static void Main(string[] args)
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
var query1 = AWEntities
.Contact
.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
.Contact
.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 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
public class MyContact
{
String _lastName;
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
count++;
}
}
}