Почему свойства навигации виртуальны по умолчанию в EF

У меня есть класс POCO, который используется в EF 6.x.

Мой вопрос. Почему свойство навигации "Сообщений" под объектом "Blog" объявлено как виртуальное?

public class Blog 
{  
    public int BlogId { get; set; }  
    public string Name { get; set; }  
    public string Url { get; set; }  
    public string Tags { get; set; }  

    public virtual ICollection<Post> Posts { get; set; }  
}

Ответ 1

Если вы определяете свойство навигации virtual, Entity Framework во время выполнения создаст новый класс (динамический прокси), полученный из вашего класса, и использует его вместо исходного класса. Этот новый динамически созданный класс содержит логику для загрузки свойства навигации при первом доступе. Это называется "ленивая загрузка". Это позволяет Entity Framework избегать загрузки всего дерева зависимых объектов, которые не нужны из базы данных.

В некоторых случаях лучше использовать "Eager Loading", особенно если вы знаете, что в какой-то момент вы будете взаимодействовать со связанными объектами.

Джулия Лерман действительно является авторитетом во всех вещах Entity Framework, и она очень хорошо объясняет этот процесс в своей статье MSDN Демистифицировать стратегию структуры сущностей: загрузка соответствующих данных

Желательная загрузка с помощью Include полезна для сценариев, в которых вы заранее знаете, что хотите, чтобы связанные данные для всех основных данных были запрошены. Но помните о двух возможных недостатках. Если у вас слишком много включений или путей перехода, платформа Entity Framework может генерировать плохо выполняющий запрос. И вы должны быть осторожны при возвращении более связанных данных, чем необходимо, благодаря простоте кодирования с Include.

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

Если вы разрабатываете веб-приложение, где все коммуникации с сервером в любом случае являются новым контекстом, Lazy Loading просто создает ненужные служебные данные для поддержания динамического класса для связанных объектов, которые никогда не будут загружены. Многие люди будут отключать ленивую загрузку в этих сценариях. В конечном счете, все же лучше всего оценить ваши SQL-запросы, которые создала EF, и определить, какие параметры будут лучше всего подходят для сценария, который вы разрабатываете.