Результаты запроса

После преобразования запроса LINQ to Entities в деревья команд и выполнения результаты запроса обычно возвращаются в качестве одного из следующих:

  • Коллекция нулевых или более типизированных объектов сущностей или проекция сложных типов в концептуальной модели.

  • Типы CLR, поддерживаемые концептуальной моделью.

  • Встроенные коллекции.

  • Анонимные типы.

После выполнения запроса к источнику данных результаты преобразуются в типы CLR и возвращаются клиенту. Материализация всех объектов осуществляется с помощью Entity Framework. Любые ошибки, возникающие вследствие неспособности сопоставления между Entity Framework и CLR, приводят к возникновению исключений во время материализации объектов.

Если выполнение запроса возвращает примитивные типы концептуальной модели, результаты состоят из типов CLR, которые являются автономными и отключенными от Entity Framework. Однако, если запрос возвращает коллекцию типизированных объектов сущностей, представленных как ObjectQuery<T>, то эти типы отслеживаются контекстом объекта. Все поведение объектов (например, дочерние или родительские коллекции, отслеживание изменений, полиморфизм и т. д.) определяются в Entity Framework. Эту функциональность можно использовать в полной мере, как определено в 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