Свойство навигации должно быть виртуальным - не требуется в 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.