Запросы объектов (платформа Entity Framework)

Универсальный класс ObjectQuery представляет запрос, который возвращает коллекцию, включающую ноль или более типизированных объектов. Класс ObjectQuery принадлежит контексту ObjectContext, содержащему соединение и сведения метаданных, необходимые для составления и выполнения запроса. Можно построить ObjectQuery с оператором new и передать строку запроса и контекст объекта в конструктор. Однако чаще используются свойства производного класса ObjectContext для получения экземпляра ObjectQuery, представляющего коллекцию наборов сущностей. Обычно ObjectContext создается в качестве подкласса классом, созданным средствами Entity Framework либо классами POCO, и свойства контекста объекта возвращают наборы сущностей как ObjectQuery (в версии .NET Framework 3.5 с пакетом обновления 1) или как ObjectSet (в версии .NET Framework 4). Класс ObjectSet расширяет класс ObjectQuery, реализуя дополнительную функциональность, например добавление и удаление объектов, в контексте типизированного набора сущностей.

ObjectQuery по умолчанию предоставляет начальный запрос, возвращающий все сущности заданного типа. Такой запрос может быть уточнен с использованием языка LINQ to Entities или методов построителя запросов.

В следующем примере выполняется запрос к контексту объекта для получения коллекции Products.

Using context As New AdventureWorksEntities
    Dim products As ObjectSet(Of Product) = context.Products

    Dim productsQuery = _
        From product In products _
        Select product

    Console.WriteLine("Product Names:")
    For Each product In productsQuery
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<Product> productsQuery = from product in context.Products
                                        select product;

    Console.WriteLine("Product Names:");
    foreach (var prod in productsQuery)
    {
        Console.WriteLine(prod.Name);
    }
}

Выполнение запроса

Запрос объектов выполняется, когда:

Примечание. Если в результате выполнения запроса из источника данных не было возвращено данных, то результаты будут содержать пустую коллекцию, а не значение null.

Запросы Entity Framework выполняются в отношении данных в источнике данных, и результаты не будут отражать новые объекты в контексте объекта. Если сущность с идентификатором, аналогичным запрошенному, уже присоединена к контексту, выполняется слияние данных, поступающих из источника данных, и данных, уже содержащихся в контексте, в соответствии с параметром MergeOption запроса. Чтобы получить данные, имеющиеся в кэше, используйте метод GetObjectStateEntries для класса ObjectStateManager. Объект ObjectStateManager управляет состоянием объектов внутри контекста объекта, поэтому, если нужно получить все добавленные, измененные и неизмененные объекты, можно передать результат побитового оператора OR для следующих значений EntityState методу GetObjectStateEntries: Added, Modified, Unchanged. Дополнительные сведения см. в блоге, где показано, как выполнять локальные запросы.

В следующем примере метод Execute вызывается для выполнения запроса:

Using context As New AdventureWorksEntities()
    Dim query As ObjectSet(Of Product) = context.Products

    ' Execute the query and get the ObjectResult. 
    Dim queryResult As ObjectResult(Of Product) = query.Execute(MergeOption.AppendOnly)
    ' Iterate through the collection of Product items. 
    For Each result As Product In queryResult
        Console.WriteLine("{0}", result.Name)
    Next
End Using
using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    ObjectSet<Product> query = context.Products;

    // Execute the query and get the ObjectResult.
    ObjectResult<Product> queryResult = query.Execute(MergeOption.AppendOnly);
    // Iterate through the collection of Product items.
    foreach (Product result in queryResult)
        Console.WriteLine("{0}", result.Name);
}

Проекция запроса

Запросы объекта часто используются для возвращения данных концептуальной модели в виде объектов сущностей, но они также могут возвращать объект DbDataRecord для вложенных результатов и анонимных проекций, а также возвращать примитивные CLR-типы для наборов отдельных значений.

И LINQ to Entities , и Entity SQL поддерживают проекции запросов. К проекциям запросов применимы следующие рекомендации.

  • Некоторые методы расширений требуют на входе коллекцию результатов. Если объект ObjectQuery представляет запрос, возвращающий коллекцию с одним скалярным результатом, и вызывается один из этих методов расширения, то вызывается исключение ArgumentException, как в следующем примере.

    ' Define a query projection that returns 
    ' a collection with a single scalar result.
    Dim scalarQuery As New ObjectQuery(Of Int32)("100", context)
    
    ' Calling an extension method that requires a collection 
    ' will result in an exception. 
    Dim hasValues As Boolean = scalarQuery.Any()
    
    // Define a query projection that returns 
    // a collection with a single scalar result.
    ObjectQuery<Int32> scalarQuery =
        new ObjectQuery<Int32>("100", context);
    
    // Calling an extension method that requires a collection
    // will result in an exception.
    bool hasValues = scalarQuery.Any();
    
  • Если существует вероятность, что ObjectQuery возвратит значение null при проекции в примитивный тип, следует использовать версию типа, допускающую значение null. В следующем запросе используется тип DateTime, допускающий значение null, поскольку свойство ShipDate объекта SalesOrderHeader может возвратить значение null.

    Dim shipDateQuery As ObjectQuery(Of Nullable(Of DateTime)) = _
        context.SalesOrderHeaders.Where("it.CustomerID = @contactId", _
            New ObjectParameter("contactId", contactId)).SelectValue(Of Nullable(Of DateTime))("it.ShipDate")
    
    ObjectQuery<Nullable<DateTime>> shipDateQuery =
        context.SalesOrderHeaders
        .Where("it.CustomerID = @contactId",
            new ObjectParameter("contactId", contactId))
        .SelectValue<Nullable<DateTime>>("it.ShipDate");
    

    Дополнительные сведения см. в разделах Типы, допускающие значение null (Руководство по программированию на Visual Basic) или Nullable Types (C# Programming Guide).

Просмотр команд хранилища

При выполнении запроса к концептуальной модели в Entity Framework происходит преобразование запроса LINQ to Entities и запроса Entity SQL , основанного на концептуальной модели, в эквивалентный запрос к источнику данных. Entity Framework предоставляет методы System.Data.Objects.ObjectQuery.ToTraceString и System.Data.EntityClient.EntityCommand.ToTraceString, позволяющие просматривать эти команды хранилища во время выполнения без необходимости выполнять трассировку источника данных. Дополнительные сведения см. в разделе Как просмотреть команды хранилища (платформа Entity Framework).

Выборка объекта по его значению EntityKey

Если известно значение ключа сущности, то ее можно получить из источника данных без явного создания и выполнения запроса объектов. Методы GetObjectByKey и TryGetObjectByKey объекта ObjectContext возвращают объект с указанным значением EntityKey в контекст объекта. Если используется метод GetObjectByKey, то необходимо обрабатывать исключения ObjectNotFoundException, возникающие, если предоставленное значение EntityKey не соответствует ни одной из существующих сущностей. Дополнительные сведения см. в разделе Как вернуть конкретный объект с помощью его ключа (платформа Entity Framework).

См. также

Основные понятия

Выполнение запроса к концептуальной модели (платформа Entity Framework)
Работа с ObjectSet (платформа Entity Framework)
Скомпилированные запросы (LINQ to Entities)