c# - существующей - metanit entity framework




Зачем использовать «virtual» для свойств класса в определениях модели Entity Framework? (4)

Для определения свойств навигации в модели виртуальным является довольно распространенным. Когда свойство навигации определяется как виртуальное, оно может воспользоваться некоторыми функциональными возможностями Entity Framework. Самый распространенный - ленивая загрузка.

Ленивая загрузка - хорошая функция многих ORM, потому что она позволяет динамически получать доступ к связанным данным из модели. Он не будет излишне запрашивать связанные данные до тех пор, пока на них не будет обращено внимание, что уменьшит предварительный запрос данных из базы данных.

Из книги «ASP.NET MVC 5 с Bootstrap и Knockout.js»

В следующем блоге: http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

В блоге содержится следующий пример кода:

public class Dinner
{
   public int DinnerID { get; set; }
   public string Title { get; set; }
   public DateTime EventDate { get; set; }
   public string Address { get; set; }
   public string HostedBy { get; set; }
   public virtual ICollection<RSVP> RSVPs { get; set; }
}

public class RSVP
{
   public int RsvpID { get; set; }
   public int DinnerID { get; set; }
   public string AttendeeEmail { get; set; }
   public virtual Dinner Dinner { get; set; }
}

Какова цель использования virtual при определении свойства в классе? Какой эффект у него есть?


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


Это позволяет Entity Framework создавать прокси-сервер вокруг виртуального объекта, чтобы свойство могло поддерживать ленивую загрузку и более эффективное отслеживание изменений. См. Какие эффекты могут иметь ключевое слово virtual в Entity Framework 4.1. Код POCO First? для более тщательного обсуждения.

Отредактируйте, чтобы уточнить «создать прокси-сервер»: «Создайте прокси-сервер». Я имею в виду конкретно то, что делает Entity Framework. Для платформы Entity Framework ваши свойства навигации должны быть помечены как виртуальные, чтобы поддерживать ленивую загрузку и эффективное отслеживание изменений. См. Требования для создания прокси POCO .
Entity Framework использует наследование для поддержки этой функции, поэтому она требует, чтобы определенные свойства были помечены как виртуальные в вашем базовом классе POCOs. Он буквально создает новые типы, которые происходят из ваших типов POCO. Таким образом, ваш POCO действует как базовый тип для динамически созданных подклассов Entity Framework. Вот что я подразумевал под «созданием прокси-сервера».

Динамически созданные подклассы, созданные Entity Framework, становятся очевидными при использовании Entity Framework во время выполнения, а не во время статической компиляции. И только если вы включите ленивые функции загрузки или изменения отслеживания Entity Framework. Если вы решите никогда не использовать ленивые функции отслеживания загрузки или изменения в Entity Framework (который не является стандартным), вам не нужно объявлять какие-либо свойства навигации как виртуальные. Затем вы отвечаете за загрузку этих свойств навигации самостоятельно, используя то, что Entity Framework называет «нетерпеливой загрузкой», или вручную извлекает связанные типы для нескольких запросов к базе данных. Однако вы можете и должны использовать ленивые функции загрузки и изменения отслеживания для ваших свойств навигации во многих сценариях.

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

Изменить, чтобы описать, почему свойства будут помечены как виртуальные

Свойства, такие как:

 public ICollection<RSVP> RSVPs { get; set; }

Не являются полями и не должны рассматриваться как таковые. Они называются геттерами и сеттерами, а во время компиляции они преобразуются в методы.

//Internally the code looks more like this:
public ICollection<RSVP> get_RSVPs()
{
    return _RSVPs;
}

public void set_RSVPs(RSVP value)
{
    _RSVPs = value;
}

private RSVP _RSVPs;

Вот почему они помечены как виртуальные для использования в Entity Framework, что позволяет динамически созданным классам переопределять внутренние функции get и set . Если ваши агенты / сеттеры свойств навигации работают для вас в вашем использовании Entity Framework, попробуйте пересмотреть их только на свойства, перекомпилировать и посмотреть, сможет ли система Entity Framework по-прежнему функционировать должным образом:

 public virtual ICollection<RSVP> RSVPs;

Я понимаю разочарование OPs, это использование виртуального не для шаблонной абстракции, для которой эффективен виртуальный модификатор defacto.

Если кто-то все еще борется с этим, я бы предложил свою точку зрения, поскольку я стараюсь, чтобы решения были простыми и жаргон до минимума:

Entity Framework в простой части использует ленивую загрузку, что эквивалентно подготовке чего-то для будущего исполнения. Это подходит для «виртуального» модификатора, но этого больше.

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

Я также упомянул об ошибке, поскольку многие свойства навигации не актуальны в первую очередь. т.е. в сценарии «Клиент / Заказ» вам не нужно ждать момента, когда заказ будет обработан для создания клиента. Вы можете, но если у вас был многоэтапный процесс для достижения этого, вы можете обнаружить необходимость сохранения данных клиента для последующего завершения или для развертывания в будущих заказах. Если были реализованы все свойства nav, вам нужно будет установить каждый внешний ключ и реляционное поле в файле save. Это действительно просто возвращает данные в память, что наносит ущерб роли настойчивости.

Поэтому, хотя это может показаться загадочным в фактическом выполнении во время выполнения, я нашел, что лучшим правилом для использования было бы: если вы выводите данные (чтение в модель просмотра или модель Serializable) и нуждаетесь в значениях перед ссылками, не делайте использовать виртуальные; Если ваша область данных собирает данные, которые могут быть неполными или необходимость поиска и не требует, чтобы каждый параметр поиска был завершен для поиска, код будет хорошо использовать ссылку, аналогичную использованию свойств значения nullable value int? долго?. Кроме того, абстрагирование вашей бизнес-логики из вашей коллекции данных до тех пор, пока она не будет введена в нее, имеет много преимуществ в производительности, аналогично созданию экземпляра объекта и его запуску при нулевом значении. Entity Framework использует много отражения и динамики, которые могут ухудшить производительность, и необходимость иметь гибкую модель, которая может масштабироваться по требованию, имеет решающее значение для управления производительностью.

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





virtual