Свойство навигации должно быть виртуальным - не требуется в ef core?
Как я помню, в EF свойство навигации должно быть виртуальным:
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; }
}
Но я смотрю EF Core и не вижу его виртуальным:
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
}
Больше не требуется?
Ответы
Ответ 1
virtual
никогда не требовалось в EF. Это было необходимо, только если вам нужна ленивая поддержка загрузки.
Так как Lazy loading еще не поддерживается EF Core, в настоящее время virtual
не имеют особого значения. Когда (и если) они добавят ленивую поддержку загрузки (для этого есть план).
Ответ 2
Это никогда не требовалось...
Благодаря другому ответу здесь я вижу, что ядро EF даже не поддерживает загрузку Lazy... Это делает виртуальное ключевое слово довольно... бесполезным в CORE
НО НОРМАЛЬНО:
1. если вы объявите свое свойство виртуальным:
Ваше виртуальное свойство (по умолчанию) сразу не будет загружено при запросе основного объекта. Он будет возвращаться из базы данных ТОЛЬКО, если вы попытаетесь получить к нему доступ, или обратитесь к одному из его компонентов.
И это называется ленивой загрузкой.
2. если вы объявите его не виртуальным:
Ваша собственность будет (по умолчанию) загружаться сразу же вместе со всем другим свойством в вашей основной сущности. Это означает, что ваша собственность будет готова к доступу: она уже была удалена. Сущность не будет запрашивать снова базу данных, потому что вы получаете доступ к этому свойству.
Это называется нетерпением загрузки.
Мое мнение:
Чаще всего я выбираю с нетерпением загрузку (не виртуальную), потому что большую часть времени мне нужно каждое свойство каждого объекта, которое будет использоваться без запроса назад (быстрее в случае, если вы действительно хотите все быстро), но если вы доступ к этому свойству только один раз в то время (вы ничего не перечисляете), и вы хотите чаще всего остальную информацию, кроме ЭТОГО, а затем сделать ее виртуальной, чтобы это свойство не замедляло остальную часть запроса только для нескольких доступ.
Надеюсь, это было ясно...
Примеры:
Где я НЕ использовал бы виртуальный (с нетерпением):
foreach(var line in query)
{
var v = line.NotVirtual; // I access the property for every line
}
Где я буду использовать виртуальную или ленивую загрузку:
foreach(var line in query)
{
if(line.ID == 509) // because of this condition
var v = line.Virtual; // I access the property only once in a while
}
последнее:
Если вы не запрашиваете более 1000 строк базы данных, то все, что вы выберете, не будет иметь большого эффекта. Кроме того, вы можете объявить это свойство виртуальным, и если вы хотите протестировать наоборот, вам просто нужно это сделать:
context.LazyLoadingEnabled = false;
Отменит виртуальный эффект.
Изменить
Для более новых версий EF:
WhateverEntities db = new WhateverEntities()
db.Configuration.LazyLoadingEnabled = false;
Ответ 3
В EF Core по умолчанию выбрал путь обескураживания ленивой загрузки.
Также я думаю, что эта функция по-прежнему не реализована после этой проблемы.
https://github.com/aspnet/EntityFramework/issues/3312
В предыдущих версиях EF свойства виртуальной навигации позволяли ленивой загрузке связанных объектов.
Я думаю, что загрузка свойств навигации теперь может быть достигнута только с помощью .Include(...)
EDIT:
Существует несколько способов загрузки связанных объектов, которые поддерживаются в Core.
Если вам интересно: https://docs.microsoft.com/en-us/ef/core/querying/related-data
Ответ 4
Все изменилось с момента написания принятого ответа. В 2018 году Lazy Loading теперь поддерживается с Entity Framework Core 2.1 для двух разных подходов.
Более простой способ состоит в использовании прокси, и для этого потребуются ленивые свойства, которые должны быть определены с помощью virtual
. Чтобы процитировать ссылку на связанную страницу:
Самый простой способ использования ленивой загрузки - установить пакет Microsoft.EntityFrameworkCore.Proxies и включить его с вызовом UseLazyLoadingProxies
. [...] EF Core затем включит lazy-load для любого свойства навигации, которое можно переопределить, то есть оно должно быть виртуальным и в классе, который может быть унаследован.
И вот приведенный пример кода:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
Существует другой способ делать Lazy Загрузка без прокси-серверов, который должен вставлять ILazyLoader
в конструктор типа данных. Это объясняется здесь.
Короче говоря, существует два способа выполнения Lazy Loading: с прокси и без них. virtual
требуется, если и только если вы хотите поддерживать Lazy Loading с помощью прокси. В противном случае это не так.
Ответ 5
Обновление: первоначальная реализация ленивой загрузки, запланированная для EF Core 2.1, потребует, чтобы свойства навигации объявлялись виртуальными. См. https://github.com/aspnet/EntityFrameworkCore/issues/10787 и, в более общем плане, отслеживать прогресс по ленивой загрузке, см. https://github.com/aspnet/EntityFrameworkCore/issues/10509.