Загрузка связанных объектов (платформа Entity Framework)

В этом разделе описаны шаблоны, которые можно использовать для загрузки связанных сущностей. В типах сущности могут определяться свойства навигации, которые представляют ассоциации в модели данных. Эти свойства можно использовать для загрузки сущностей, которые связаны с возвращенной сущностью посредством определенной ассоциации. Когда сущности формируются на основе модели данных, свойства навигации создаются для сущностей в обоих элементах ассоциации. Данные свойства навигации возвращают либо ссылку на элемент «один» в связи типа «один ко многим» или «многие к одному», либо коллекцию элементов «многие» в связи типа «один ко многим» или «многие ко многим». Дополнительные сведения см. в разделах Свойства навигации и Определение отношений и управление отношениями (платформа Entity Framework).

В следующих шаблонах описаны способы, которые можно использовать для загрузки связанных сущностей.

Загрузка шаблона Описание

Указывается в запросе

Можно сформировать запрос Entity SQL или LINQ to Entities , который будет явно переходить по связям при помощи свойств навигации. При выполнении такого запроса происходит возврат связанных сущностей, которые включены в качестве свойств навигации в самую внешнюю проекцию запроса. Дополнительные сведения см. в разделе

Как переходить по связям с помощью свойств навигации (платформа Entity Framework).

Явная загрузка

При явной загрузке сущностей в ObjectContext требуется несколько циклов обмена данными с базой данных; кроме того, могут потребоваться несколько активных результирующих наборов, однако объем возвращаемых данных ограничен только загружаемыми сущностями. Для явной выборки связанных сущностей из источника данных используйте метод Load для объекта EntityCollection или EntityReference или метод LoadProperty для объекта ObjectContext. При каждом вызове метода Load открывается соединение с базой данных для получения связанной информации. Это гарантирует, что запрос никогда не выполняется без явного обращения к связанной сущности. Явная загрузка является поведением по умолчанию для среды Entity Framework .

Bb896272.note(ru-ru,VS.100).gifПримечание
До вызова метода Load в ObjectContext уже загружен небольшой объем информации о связанной сущности.

Дополнительные сведения см. в подразделе Explicitly Loading Related Objects этого раздела.

Отложенная загрузка

Во время загрузки этого типа связанные сущности загружаются из источника данных автоматически при доступе к свойству навигации. Используя загрузку этого типа, необходимо учитывать, что доступ к каждому свойству навигации приводит к выполнению отдельного запроса к источнику данных, если сущность еще не находится в ObjectContext.

Дополнительные сведения см. в подразделе Lazy Loading этого раздела.

Безотложная загрузка

или

Определение путей запроса с включением

Если известен точный вид графа связанных сущностей, необходимых для конкретного приложения, то можно применить метод Include к объекту ObjectQuery для определения пути запроса, управляющего тем, какие связанные сущности должны быть возвращены в составе начального запроса. При определении пути запроса для возврата всех сущностей, которые задаются путем в одном результирующем наборе, требуется только один запрос к базе данных. Для каждого объекта, возвращаемого запросом, загружаются все связанные сущности того типа, который задан в пути.

Дополнительные сведения см. в подразделе Defining a Query Path to Shape Query Results этого раздела.

Явная загрузка связанных объектов сущности

Чтобы загрузить связанные сущности явным образом, необходимо вызвать метод Load для связанного элемента, возвращенного свойством навигации. Для связи типа «один ко многим» вызовите метод Load для объекта EntityCollection, а для взаимно-однозначной связи — метод Load для объекта EntityReference. При работе с сущностями POCO метод LoadProperty применяется для объекта ObjectContext. Дополнительные сведения см. в разделе Загрузка связанных сущностей POCO (платформа Entity Framework). Метод LoadProperty также может использоваться для сущностей, которые являются производными от EntityObject. Эти методы выполняют загрузку данных связанного объекта в контекст объекта. Если запрос возвращает результаты, то для коллекции объектов можно выполнить перечисление, использовав цикл foreach (For Each...Next в Visual Basic), и по условию вызывать метод Load для свойств EntityReference и EntityCollection каждой сущности в результатах.

Bb896272.note(ru-ru,VS.100).gifПримечание
Если метод Load вызывается во время перечисления foreach (C#) или For Each (Visual Basic), Entity Framework пытается открыть новый модуль чтения данных.Эта операция завершится ошибкой, если не был включен режим MARS путем задания multipleactiveresultsets=true в строке соединения.Дополнительные сведения см. в разделе Использование режима MARS на веб-узле MSDN.Кроме того, результаты запроса можно загрузить в коллекцию List, при этом модуль чтения данных будет закрыт и можно будет перечислить коллекцию, чтобы загрузить упоминаемые сущности.

Дополнительные сведения см. в разделе Как явно загружать связанные объекты (платформа Entity Framework).

Указание пути запроса для формирования результатов запроса

Чтобы указать путь запроса, передайте строковое представление графа объектов методу Include в запросе ObjectQuery. Этот путь указывает, какие связанные сущности должны быть возвращены при выполнении запроса объектов. Например, путь запроса, указанный в запросе для объектов Contact, гарантирует, что все связанные объекты SalesOrderHeader и SalesOrderDetail будут возвращены. Это показано в следующем запросе.

' Define a LINQ query with a path that returns 
' orders and items for a contact. 
Dim contacts = (From contact In context.Contacts.Include("SalesOrderHeaders.SalesOrderDetails") _
    Select contact).FirstOrDefault()
// Define a LINQ query with a path that returns 
// orders and items for a contact.
var contacts = (from contact in context.Contacts
              .Include("SalesOrderHeaders.SalesOrderDetails")
                select contact).FirstOrDefault();

При указании путей запроса необходимо учитывать следующее.

  • Пути запроса можно использовать с методами построителя запросов и запросами LINQ.

  • При вызове метода Include путь запроса действителен только для возвращаемого экземпляра ObjectQuery. Другие экземпляры запроса ObjectQuery и контекст объекта не затрагиваются.

  • Поскольку метод Include возвращает объект запроса, для объекта ObjectQuery этот метод можно вызывать многократно, чтобы включать сущности из нескольких связей, как в следующем примере:

    ' Create a SalesOrderHeader query with two query paths, 
    ' one that returns order items and a second that returns the 
    ' billing and shipping addresses for each order. 
    Dim query As ObjectQuery(Of SalesOrderHeader) = context.SalesOrderHeaders.Include("SalesOrderDetails").Include("Address")
    
    // Create a SalesOrderHeader query with two query paths, 
    // one that returns order items and a second that returns the 
    // billing and shipping addresses for each order.
    ObjectQuery<SalesOrderHeader> query =
        context.SalesOrderHeaders.Include("SalesOrderDetails").Include("Address");
    
  • Использование путей запроса может привести к тому, что над источником данных будут выполняться сложные команды из, на первый взгляд, простых запросов к объектам. Это происходит, поскольку для возвращения связанных объектов в одном запросе необходимо одно или несколько соединений, что приводит к избыточности данных для каждой связанной сущности, возвращаемой из источника данных. Сложность будет выше в запросах к сложным моделям, таким как сущность с наследованием или путь, содержащий связи «многие ко многим». Используйте метод ToTraceString, чтобы увидеть команду, которая будет сформирована методом ObjectQuery. Когда путь запроса содержит слишком много связанных объектов или эти объекты содержат слишком много строковых данных, источник данных может оказаться не в состоянии выполнить запрос. Это происходит, если запросу требуется промежуточное временное хранилище, которое превышает возможности источника данных. В этом случае можно снизить сложность запроса к источнику данных путем явной загрузки связанных объектов или включения отложенной загрузки. Если после оптимизации сложного запроса происходит частое наступление события истечения времени ожидания, попробуйте увеличить значение времени ожидания посредством установки значения свойства CommandTimeout.

Дополнительные сведения см. в разделе Как использовать пути запросов для формирования результатов (платформа Entity Framework).

Отложенная загрузка объектов сущности

Платформа Entity Framework поддерживает отложенную загрузку связанных сущностей. В среде выполнения Entity Framework значением по умолчанию для свойства LazyLoadingEnabled в экземпляре ObjectContext является false. Однако, если для создания новой модели и соответствующих формируемых классов используются средства Entity Framework , в конструкторе контекста объекта параметр LazyLoadingEnabled имеет значение true. Если включена отложенная загрузка, то связанные сущности не будут загружаться из источника данных, пока к ним не будет выполнен доступ программным путем с помощью метода доступа get свойства навигации. Чтобы отключить отложенную загрузку, задайте для свойства LazyLoadingEnabled значение false в экземпляре ObjectContextOptions, возвращаемом свойством System.Data.Objects.ObjectContext.ContextOptions.

Отложенная загрузка может использоваться вместе с активной загрузкой. В этом случае базовый граф данных может быть определен с помощью путей запроса, а дополнительные связанные сущности, не включенные в исходные пути запроса, могут загружаться по мере необходимости. Дополнительные сведения см. в разделе Как использовать отложенную загрузку для загрузки связанных объектов (платформа Entity Framework).

При использовании «неспешной» загрузки следует обратить внимание на следующие аспекты.

  • Отложенная загрузка поддерживается для свойств навигации, возвращающих одну сущность (например, EntityReference) или коллекцию сущностей (например, EntityCollection).

  • Если отложенная загрузка включена, а связанная сущность уже загружена, то она не будет загружаться повторно.

  • Отложенная загрузка поддерживается для сущностей в состоянии Detached. В этом случае связанные объекты также возвращаются в состоянии Detached.

  • Поведение «неспешной» загрузки определяется экземпляром ObjectContext, который используется для получения объекта из источника данных (даже если сущность была загружена с NoTracking MergeOption), или экземпляром, к которому объект был добавлен или прикреплен. Поэтому поведение «неспешной» загрузки нельзя изменить после удаления контекста, а все последующие операции «неспешной» загрузки завершаться с ошибкой.

  • При сериализации сущностей может понадобиться отключить «неспешную» загрузку. В противном случае отложенная загрузка будет запускаться и в сериализуемую сущность может быть включено больше данных, чем ожидалось.

При использовании отложенной загрузки с объектами РОСО следует учесть дополнительные сведения. Дополнительные сведения см. в разделе Загрузка связанных сущностей POCO (платформа Entity Framework).

Запрос связанных объектов сущности

Вызов метода CreateSourceQuery для EntityCollection позволяет выполнять запросы к связанным объектам без предварительной загрузки объектов в коллекцию. CreateSourceQuery возвращает ObjectQuery который при выполнении возвращает тот же набор объектов, который возвращается при вызове метода Load. К этому запросу объектов можно применять методы построителя запросов, чтобы осуществлять дополнительную фильтрацию объектов, загруженных в коллекцию. Дополнительные сведения см. в разделе Как выполнять запросы к связанным объектам в коллекции EntityCollection (платформа Entity Framework).

Объект ObjectQuery возвращает данные сущности в виде сущностей. Однако если свойство навигации включено в проекцию самого внешнего запроса, запрос также возвращает связанные сущности, к которым обращается навигация. Дополнительные сведения см. в разделе Как переходить по связям с помощью свойств навигации (платформа Entity Framework).

Замечания о производительности

При выборе шаблона для загрузки связанных сущностей необходимо учитывать особенности каждого подхода с точки зрения количества и времени соединений, устанавливаемых с источником данных, в сравнении с объемом возвращенных данных и сложностью использования единственного запроса. Безотложная загрузка приводит к возврату всех связанных сущностей вместе с запрошенными сущностями в единственном запросе. Это означает, что, несмотря на установку только одного соединения с источником данных, в начальном запросе происходит возврат большего объема данных. Кроме того, применение путей запроса приводят к получению более сложного запроса из-за дополнительных соединений, которые требуются в запросе к источнику данных.

Применение явной и «неспешной» загрузки позволяет отложить выполнение запроса к данным связанного объекта до тех пор, пока эти данные действительно не потребуются. Это приводит к получению менее сложного начального запроса, который возвращает меньший суммарный объем данных. Но при каждой идущей подряд загрузке связанного объекта устанавливается соединение с источником данных и выполняется запрос. В случае отложенной загрузки это соединение устанавливается каждый раз, когда происходит доступ к свойству навигации, притом что связанная сущность еще не загружена. Если необходимо управлять связанными сущностями, возвращаемыми исходным запросом, или синхронизацией загрузки связанных сущностей из источника данных, то можно отключить отложенную загрузку. Отложенная загрузка включается в конструкторе контекста объекта, сформированного Entity Framework .

Дополнительные сведения см. в разделе Вопросы производительности (платформа Entity Framework).

См. также

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

Выполнение запроса к концептуальной модели (платформа Entity Framework)
Запросы объектов (платформа Entity Framework)
Методы построителя запросов (платформа Entity Framework)