В следующем блоге: 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
при определении свойства в классе? Какой эффект это имеет?
c#
class
properties
virtual
Гари Джонс
источник
источник
Ответы:
Это позволяет Entity Framework создавать прокси вокруг виртуального свойства, чтобы свойство могло поддерживать отложенную загрузку и более эффективное отслеживание изменений. См. Какие эффекты могут иметь виртуальное ключевое слово в Entity Framework 4.1 POCO Code First? для более тщательного обсуждения.
Изменить, чтобы уточнить "создать прокси вокруг": под "создать прокси вокруг" я имею в виду конкретно то, что делает Entity Framework. Entity Framework требует, чтобы ваши навигационные свойства были помечены как виртуальные, чтобы поддерживалась отложенная загрузка и эффективное отслеживание изменений. См. Требования для создания прокси POCO .
Entity Framework использует наследование для поддержки этой функциональности, поэтому требует, чтобы определенные свойства были помечены как виртуальные в ваших POCO базового класса. Он буквально создает новые типы, которые происходят от ваших типов POCO. Таким образом, ваш POCO действует как базовый тип для динамически создаваемых подклассов Entity Framework. Вот что я имел в виду под «создать прокси вокруг».
Динамически создаваемые подклассы, которые создает Entity Framework, становятся очевидными при использовании Entity Framework во время выполнения, а не во время статической компиляции. И только если вы включите ленивую загрузку Entity Framework или измените функции отслеживания. Если вы решите никогда не использовать функции отложенной загрузки или отслеживания изменений Entity Framework (что не является значением по умолчанию), вам не нужно объявлять какие-либо из ваших свойств навигации как виртуальные. Затем вы несете ответственность за загрузку этих свойств навигации самостоятельно, используя то, что Entity Framework называет «быстрой загрузкой», или вручную извлекая связанные типы по нескольким запросам к базе данных. Вы можете и должны использовать ленивую загрузку и изменять функции отслеживания для своих навигационных свойств во многих сценариях.
Если вы создадите автономный класс и отметите свойства как виртуальные, а просто создадите и будете использовать экземпляры этих классов в своем собственном приложении, полностью выходя за рамки Entity Framework, тогда ваши виртуальные свойства не принесут вам никакой пользы. своя.
Изменить, чтобы описать, почему свойства будут помечены как виртуальные
Свойства, такие как:
Не являются полями и не должны рассматриваться как таковые. Они называются геттерами и сеттерами, и во время компиляции они преобразуются в методы.
Вот почему они помечены как виртуальные для использования в Entity Framework, это позволяет динамически создаваемым классам переопределять внутренне сгенерированные
get
иset
функции. Если ваш получатель / установщик свойств навигации работает для вас при использовании Entity Framework, попробуйте изменить их на просто свойства, перекомпилировать и посмотреть, может ли Entity Framework по-прежнему функционировать должным образом:источник
virtual
Ключевое слово в C # позволяет метод или свойство быть переопределены дочерними классами. Дополнительную информацию см. В документации MSDN по ключевому слову «virtual».ОБНОВЛЕНИЕ: Это не отвечает на вопрос, как в настоящее время задается, но я оставлю это здесь для любого, кто ищет простой ответ на оригинальный , не описательный вопрос, заданный.
источник
virtual
свойствами через Entity Framework - даже если это не указано в заголовке OP. Принятый ответ таков, потому что он касается стороны Entity Framework и того, как / почемуvirtual
свойства используются в этом контексте.Я понимаю разочарование OPs, такое использование виртуального не для шаблонной абстракции, для которой эффективный модификатор defacto эффективен.
Если кто-то все еще борется с этим, я бы предложил свою точку зрения, поскольку я стараюсь сохранить решения простыми и жаргоном к минимуму:
Простая структура Entity Framework использует ленивую загрузку, что эквивалентно подготовке чего-либо для будущего выполнения. Это соответствует модификатору 'virtual', но это еще не все.
В Entity Framework использование свойства виртуальной навигации позволяет обозначать его как эквивалент обнуляемого внешнего ключа в SQL. Вы не должны охотно присоединяться к каждой таблице ключей при выполнении запроса, но когда вам нужна информация - она становится управляемой спросом.
Я также упомянул nullable, потому что многие свойства навигации поначалу не актуальны. т.е. в сценарии клиент / заказы вам не нужно ждать, пока будет обработан заказ, чтобы создать клиента. Вы можете, но если у вас был многоэтапный процесс для достижения этой цели, вам может потребоваться сохранить данные клиента для последующего завершения или для размещения в будущих заказах. Если бы все свойства nav были реализованы, вам нужно было бы установить каждый внешний ключ и реляционное поле при сохранении. Это на самом деле просто возвращает данные обратно в память, что побеждает роль постоянства.
Поэтому, хотя это может показаться загадочным при реальном выполнении во время выполнения, я обнаружил, что лучшее практическое правило для использования будет таким: если вы выводите данные (считываете в модель представления или в сериализуемую модель) и вам нужны значения перед ссылками, не использовать виртуальный; Если ваша область собирает данные, которые могут быть неполными или требовать поиска и не требовать, чтобы каждый поисковый параметр был завершен для поиска, код будет эффективно использовать ссылку, аналогично использованию свойств int со значением nullable. длинный?. Кроме того, абстрагирование вашей бизнес-логики от сбора данных до тех пор, пока не потребуется вводить их, имеет много преимуществ для производительности, подобно созданию экземпляра объекта и его запуску с нуля. Entity Framework использует много отражений и динамики, которые могут ухудшить производительность, и необходимость иметь гибкую модель, которая может масштабироваться по требованию, имеет решающее значение для управления производительностью.
Для меня это всегда имело больше смысла, чем использование перегруженного технического жаргона, такого как прокси, делегаты, обработчики и тому подобное. Как только вы достигнете своего третьего или четвертого языка программирования, он может запутаться в этом.
источник
Из книги "ASP.NET MVC 5 с Bootstrap и Knockout.js"
источник
В контексте EF пометка свойства как виртуального позволяет EF использовать ленивую загрузку для его загрузки. Чтобы ленивая загрузка работала, EF должен создать прокси-объект, который переопределяет ваши виртуальные свойства с помощью реализации, которая загружает ссылочную сущность при первом обращении к ней. Если вы не отметите свойство как виртуальное, то отложенная загрузка не будет работать с ним.
источник
Ключевое слово virtual используется для изменения метода, свойства, индексатора или объявления события и позволяет переопределять его в производном классе. Например, этот метод может быть переопределен любым классом, который его наследует:
источник
Мы не можем говорить о виртуальных членах, не обращаясь к полиморфизму . Фактически, функция, свойство, индексатор или событие в базовом классе, помеченные как виртуальные, позволяют переопределять производный класс.
По умолчанию члены класса не виртуальны и не могут быть помечены как таковые, если используются модификаторы static, abstract, private или override.
Пример Рассмотрим метод ToString () в System.Object . Поскольку этот метод является членом System.Object, он наследуется во всех классах и предоставит методы ToString () для всех них.
Вывод предыдущего кода:
Давайте рассмотрим, что мы хотим изменить стандартное поведение методов ToString (), унаследованных от System.Object в нашем классе Company. Для достижения этой цели достаточно использовать ключевое слово override, чтобы объявить другую реализацию этого метода.
Теперь, когда виртуальный метод вызывается, среда выполнения проверит наличие переопределяющего члена в своем производном классе и вызовет его, если он есть. Выход нашего приложения будет:
Фактически, если вы проверите класс System.Object, вы обнаружите, что метод помечен как виртуальный.
источник