Entity Framework 4.1 Виртуальные свойства

Если я объявил связь с сущностью в моей модели как виртуальной, тогда нет необходимости использовать оператор Include в моем запросе LINQ, правильно? -

Для примера: это мой модельный класс:

public class Brand
{
    public int BrandID { get; set; }
    public string BrandName { get; set; }
    public string BrandDesc { get; set; }
    public string BrandUrl { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

Теперь для указанного выше класса модели мне не нужно использовать var brandsAndProduct = pe.Brands.Include("Products").Single(brand => brand.BrandID == 22);.

Вместо этого я могу просто использовать простой var brandsAndProduct = pe.Brands.Where(brand => brand.BrandID == 22);, и я буду автоматически иметь связанный объект, доступный при доступе.

Правильно ли я в своем понимании?

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

Ответ 1

Вы правы, но правило более сложное, чтобы оно действительно работало, как ожидалось. Если вы определяете свое навигационное свойство virtual, EF во время выполнения создаст новый класс (динамический прокси), полученный из вашего класса Brand, и вместо него используйте его. Этот новый динамически созданный класс содержит логику для загрузки свойства навигации при первом доступе. Эта функция называется ленивой загрузкой (или более прозрачной ленивой загрузкой).

Какие правила должны быть выполнены для выполнения этой работы:

  • Все свойства навигации в классе должны быть virtual
  • Невозможно отключить создание динамического прокси (context.Configuration.ProxyCreationEnabled). Он включен по умолчанию.
  • Ленивая загрузка не должна быть отключена (context.Configuration.LazyLoadingEnabled). Он включен по умолчанию.
  • Объект должен быть присоединен (по умолчанию, если вы загружаете объект из базы данных) в контекст и контекст не должен быть удален = ленивая загрузка работает только в пределах контекста жизни, используемого для его загрузки из базы данных (или там, где прокси-объект был присоединен)

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

Использование ленивой загрузки и быстрой загрузки зависит от ваших потребностей, а также от производительности. Include загружает все данные в один запрос базы данных, но может привести к огромному набору данных при использовании большого количества включений или загрузки множества объектов. Если вы уверены, что вам понадобится Brand и все Products для обработки, вы должны использовать активную загрузку.

В свою очередь используется ленивая загрузка, если вы не уверены в том, какое навигационное свойство вам понадобится. Например, если вы загружаете 100 брендов, но вам нужно будет получать доступ только к продуктам одного бренда, нет необходимости загружать продукты для всех брендов в исходный запрос. Недостатком ленивой загрузки является отдельный запрос (обратный вызов базы данных) для каждого свойства навигации = > , если вы загружаете 100 брендов без включения, и вы получите доступ к свойству Products в каждом экземпляре Brand, ваш код будет генерировать еще 100 запросов для заполнения этих свойства навигации = загруженная загрузка будет использовать только один запрос, но ленивая загрузка использовала 101 запрос (это называется проблемой N + 1).

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

Явная загрузка имеет такие же недостатки, как и ленивая загрузка, но вы должны запускать ее вручную:

context.Entry(brand).Collection(b => b.Products).Load();

Основными преимуществами для явной загрузки является способность фильтровать отношение. Вы можете использовать Query() до Load() и использовать любую фильтрацию или даже нетерпеливую загрузку вложенных отношений.