Легкая, ленивая и явная загрузка в EF6

Я прочитал этот tutorial и этот article но я не понимаю точно использование каждого типа загрузки.

Объяснение

У меня есть этот POCO:

public partial class dpc_gestion
{
    public dpc_gestion()
    {
        this.ass_reunion_participant = new HashSet<ass_reunion_participant>();
        this.dpc_participant = new HashSet<dpc_participant>();
        this.dpc_reunion = new HashSet<dpc_reunion>();
    }

    public int dpc_id_pk { get; set; }
    public Nullable<int> dpc_id_gdp_fk { get; set; }
    public Nullable<int> dpc_id_theme { get; set; }
    public int dpc_id_animateur_fk { get; set; }
    public Nullable<System.DateTime> dpc_date_creation { get; set; }
    public Nullable<System.DateTime> dpc_date_fin { get; set; }
    public Nullable<System.DateTime> dpc_date_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_let_engag_anim { get; set; }
    public Nullable<bool> dpc_flg_fsoins_anim { get; set; }
    public virtual ICollection<ass_reunion_participant> ass_reunion_participant { get; set; }
    public virtual theme_dpc theme_dpc { get; set; }
    public virtual gdp_groupe_de_pair gdp_groupe_de_pair { get; set; }
    public virtual ICollection<dpc_participant> dpc_participant { get; set; }
    public virtual ICollection<dpc_reunion> dpc_reunion { get; set; }
}

Я понял это:

  • Для ленивой загрузки: потому что нагрузка ленива, если я вызываю dbset dpc_gestion, все свойства навигации не будут загружаться. Этот тип загрузки является лучшим в производительности и быстроте. Он включен по умолчанию, и если я хотел бы снова включить его, я должен установить:

    context.Configuration.ProxyCreationEnabled = true;    
    context.Configuration.LazyLoadingEnabled = true;
    
  • Для активной загрузки Он не ленив: он загружал все свойства навигации, когда я загружаю dpc_gestion. Свойства навигации можно загрузить с помощью метода include. Чтобы включить этот тип загрузки:

    context.Configuration.LazyLoadingEnabled = false;
    
  • Для явной загрузки Это похоже на нетерпеливую загрузку, но мы используем Load метод вместо include.

Итак, я хотел бы знать:

  • Если это небольшое резюме верно?
  • Если это правда, в чем разница между нетерпеливой и явной загрузкой?
  • Если я использую ленивую загрузку, и я вызываю например dpc_gestion.dpc_participant, загружаются ли свойства навигации? или я получу исключение?
  • Есть ли случай, когда интенсивная загрузка или явная загрузка лучше, чем ленивая загрузка в производительности и отзывчивости?

Спасибо

Ответ 1

Если это небольшое резюме верно?

Да.

Если это правда, в чем разница между нетерпеливой и явной загрузкой?

Нежелательная загрузка противоположна Lazy loading, но Явная загрузка похожа на ленивую загрузку, за исключением того, что: вы явно извлекаете связанные данные в код; это не происходит автоматически при доступе к навигационному свойству. Вы загружаете связанные данные вручную, получая запись диспетчера состояния объекта для объекта и вызывая метод Collection.Load для коллекций или метод Reference.Load для свойств, которые содержат один объект.

От techblog:

Оживленная загрузка:

Ожидаемая загрузка - это напротив Lazy loading, которая: Процесс загрузки определенного набора связанных объектов вместе с объектами которые были запрошены в запросе.

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

Явная загрузка определяется как: когда объекты возвращаются запросом, связанные объекты не загружаются одновременно. По умолчанию они не загружается до явного запроса с использованием метода Load на свойства навигации.

и

Если я использую ленивую загрузку, и я вызываю, например, dpc_gestion.dpc_participant, загружаются ли свойства навигации? или я получу исключение?

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

Есть ли случай, когда быстрая загрузка или явная загрузка были лучше чем ленивая загрузка в производительности и отзывчивости?

Желаемая загрузка обычно более эффективна, когда вам нужны связанные данные для всех извлеченных строк первичной таблицы. А также, когда отношения не слишком велики, интенсивная загрузка будет хорошей практикой для сокращения дальнейших запросов на сервере. Но когда вы знаете, что вам не понадобится недвижимость мгновенно, тогда ленивая загрузка может быть хорошим выбором. А также желаемая загрузка - это хороший выбор в ситуации, когда ваш контекст db будет удален, а ленивая загрузка больше не может быть. Например, рассмотрим следующее:

public List<Auction> GetAuctions()
{
    using (DataContext db = new DataContext())
    {
        return db.Auctions.ToList();
    }
}

После вызова этого метода вы не можете загружать связанный объект лениво, потому что db расположен, и поэтому Eager Loading будет лучшим выбором здесь.

Еще одна вещь, которую нужно отметить: Lazy loading будет производить несколько запросов SQL, а загружать загружать данные одним запросом. Желаемая загрузка также является хорошим выбором для решения проблемы n + 1 в ORM. Взгляните на это сообщение: Что выбирает проблема n + 1?

Ответ 2

Вопрос 1 и 2:

Ваше объяснение ленивой загрузки и надежной загрузки верное.
Использование явной загрузки немного отличается от описанной.

EntityFramework возвращает IQueryable объекты, которые по существу содержат запрос к базе данных. Но они не выполняются до тех пор, пока они не будут перечислены.
Load выполняет запрос, чтобы его результаты сохранялись локально.
Вызов Load совпадает с вызовом ToList и выбрасывает его List, не имея накладных расходов на создание List.

Вопрос 3:

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

Вопрос 4:

В отключенных случаях (например, сетевое приложение) вы не можете использовать ленивую загрузку, потому что эти объекты переводятся в DTO, а затем не отслеживаются EntityFramework.

Кроме того, если вы знаете, что собираетесь использовать свойство навигации, его хорошая практика - загрузить его с нетерпением, поэтому вам не придется ждать, пока они загружаются из базы данных.
Например, скажем, вы сохраняете результат в списке и привязываете его к WPF DataGrid. Если DataGrid обращается к еще не загруженному ресурсу, пользователь испытывает заметный тайм-аут, пока не отобразится это свойство. Кроме того, приложение не будет отвечать во время загрузки (если вы не загружаете асинхронно).