Запросы объектов (платформа 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);
}
}
Выполнение запроса
Запрос объектов выполняется, когда:
Запрос перечисляется с помощью инструкции foreach (C#) или For Each (Visual Basic).
Запрос перечисляется операцией коллекции, например ToArray, ToDictionary или ToList.
При явном вызове метода Execute.
Операторы LINQ, например First или Any, задаются во внешней части запроса. Дополнительные сведения см. в разделе Методы построителя запросов (платформа Entity Framework).
Примечание. Если в результате выполнения запроса из источника данных не было возвращено данных, то результаты будут содержать пустую коллекцию, а не значение 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)