Результаты запроса
После преобразования запроса LINQ to Entities в деревья команд и последующего выполнения результаты запроса обычно возвращаются в одной из следующих форм.
Коллекция, содержащая ноль, один или несколько типизированных объектов сущностей или проекцию сложных типов в модели EDM.
Типы CLR, поддерживаемые моделью EDM.
Встроенные коллекции.
Анонимные типы.
При выполнении запроса к источнику данных результаты материализуются в типы CLR и возвращаются клиенту. Материализация объектов полностью обеспечивается платформой Entity Framework. Любые ошибки, вызванные невозможностью сопоставления объектов платформы Entity Framework и среды CLR, вызовут исключения во время материализации объекта.
Если в результате выполнения запроса возвращаются типы-примитивы модели EDM, то результаты состоят из изолированных типов CLR, которые не соединены с платформой Entity Framework. Однако если запрос вернул коллекцию типизированных объектов сущностей, представленных ObjectQuery, то эти типы отслеживаются контекстом объекта. Все операции с объектом (дочерние и родительские коллекции, отслеживание изменений, полиморфизм и т. д.) выполнятся согласно определениям Entity Framework. Эти функции можно могут быть использованы в пределах, определяемых Entity Framework. Дополнительные сведения см. в разделе Общие сведения о службах объектов (платформа Entity Framework).
Типы структур, возвращаемые из запросов (например, анонимные и сложные типы, допускающие значение NULL), могут иметь значение null. Свойство EntityCollection возвращаемой сущности также может иметь значение null. Это может произойти в результате проецирования свойства коллекции для сущности, имеющей значение null, например, при вызове метода FirstOrDefault для объекта ObjectQuery, который не содержит элементов.
В некоторых ситуациях может показаться, что запрос создает материализованный результат во время выполнения, но в действительности запрос будет выполняться на сервере и объект сущности никогда не окажется материализован в среде CLR. Это может вызвать проблемы, если приложение рассчитывает на побочные эффекты материализации.
В следующем примере имеется пользовательский класс MyContact
со свойством LastName
. При присваивании значения свойству LastName
переменная count
увеличивается на единицу. Если выполнить два приведенных ниже запроса, то первый запрос увеличит значение count
на единицу, а второй — нет. Причина этого заключается в том, что во втором запросе свойство LastName
спроецировано из результатов, а класс MyContact
не создается, поскольку он не является необходимым для выполнения запроса в хранилище.
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++;
}
}
}