Pytanie właściwość nawigacji powinna być wirtualna - nie jest wymagana w ef core?


Jak pamiętam w EF Właściwość navigation powinna być wirtualna:

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; }  
}

Ale patrzę Rdzeń EF i nie widzę tego jako wirtualnego:

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; }
    }

Czy to już nie jest wymagane?


16
2018-01-26 19:14


pochodzenie




Odpowiedzi:


virtual nigdy nie był wymagany w EF. To było potrzebne tylko wtedy, gdy potrzebujesz leniwego ładowania.

Od Leniwe ładowanie nie jest jeszcze wspierane przez EF Core, obecnie virtual nie mają specjalnego znaczenia. Byłoby wtedy, gdyby (i jeśli) dodali leniwą obsługę ładowania (istnieje plan za to).

Aktualizacja: Począwszy od wersji EF Core 2.1, Powolne ładowanie jest teraz obsługiwany. Ale jak tylko nie dodasz Microsoft.EntityFrameworkCore.Proxies pakiet i włącz go przez UseLazyLoadingProxies, oryginalna odpowiedź nadal obowiązuje.

Jednak jeśli to zrobisz, rzeczy całkowicie się zmienią ze względu na brak kontroli opt-in w początkowej realizacji - to wymaga  wszystko Twoje właściwości nawigacyjne mają być virtual. Co nie ma dla mnie sensu, lepiej nie używać tego, dopóki nie zostanie naprawiony. Jeśli naprawdę potrzebujesz leniwego ładowania, skorzystaj z alternatywy Leniwe ładowanie bez serwerów proxy  podejście, w tym przypadku ponownie virtual nie ma znaczenia.


29
2018-01-26 19:22



Jeśli nie ma specjalnego znaczenia, dlaczego szkielet generuje wszystkie właściwości nawigacyjne z wirtualnymi? - Camilo Terevinto
@CamiloTerevinto Na wszelki wypadek? Domyślnie? Teraz to naprawdę nie ma znaczenia. - Ivan Stoev
@AntoinePelletier Nie wiem też - w ogóle nie używam rusztowania. Ale znając aktualny stan EF Core - błędy, niekompletne funkcje, dziwne wewnętrzne wyjątki od prostych trafnych zapytań, co to za oprzyrządowanie (w szczególności na rusztowanie) powinno być mniej niepokojące dla osób używających go. - Ivan Stoev
Obecnie tak (brak efektu). Może jednak w przyszłości. O to chodzi. - Ivan Stoev
Z Scaffold-DbContext w EF Core 1.X wszystkie właściwości nawigacyjne były wirtualne. Po ponownym uaktualnieniu do wersji EF Core 2.X po prostu ponownie je sfotografowałem, a wszystkie właściwości nawigacyjne nie są już wirtualne. - Johnny Oshika


Rzeczy się zmieniły odkąd przyjęto zaakceptowaną odpowiedź. W 2018 r. Lazy Loading jest teraz obsługiwany od Entity Framework Core 2.1 dla dwóch różnych podejść.

Prostszy sposób z tych dwóch używa proxy, a to wymaga, aby pożądane właściwości były leniwie ładowane do zdefiniowania za pomocą virtual. Aby zacytować na połączonej stronie:

Najprostszym sposobem na użycie leniwego ładowania jest zainstalowanie pakietu Microsoft.EntityFrameworkCore.Proxies i włączenie go za pomocą wywołania UseLazyLoadingProxies. [...] EF Core następnie włączy leniwy ładunek dla każdej właściwości nawigacji, którą można przesłonić - to znaczy, musi być wirtualna i może być odziedziczona po klasie.

Oto przykładowy kod:

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; }
}

Istnieje inny sposób robienia Lazy Loading bez proxy, który polega na wstrzykiwaniu ILazyLoader do konstruktora typu danych. Zostało to wyjaśnione tutaj.

W skrócie, istnieją dwa sposoby na wykonanie Lazy Loading: zi bez serwerów proxy. virtual jest wymagany wtedy i tylko wtedy, gdy chcesz wspierać Lazy Loading z serwerami proxy. W przeciwnym razie nie jest.


14
2018-04-02 18:49



Rzeczy się zmieniły, ale punkt w mojej odpowiedzi jest nadal aktualny - właściwości nawigacji są nadal nie wymagane z wyjątkiem postawienia się w sytuacji, w której oni są wymagane z powodu wydanej niekompletnej funkcji. Gdy leniwy ładowanie z serwerami proxy zostanie naprawione, twoja odpowiedź zostanie unieważniona i znowu virtualnie będzie wymagane tak, jak powinno. - Ivan Stoev


Słowo klucza wirtualnego nigdy nie było WYMAGANE ... Jest opcjonalne.

Co to zmienia?

1. jeśli zadeklarujesz swoją własność wirtualną:

Twoja własność wirtualna (domyślnie) nie zostanie załadowana od razu podczas odpytywania głównego obiektu. Będzie on odzyskiwany TYLKO z bazy danych, jeśli spróbujesz uzyskać do niego dostęp lub uzyskasz dostęp do jednego z jej składników.

A to nazywa się leniwym ładowaniem.

2. jeśli zadeklarujesz to jako nie-wirtualne:

Twoja własność (domyślnie) zostanie załadowana od razu wraz ze wszystkimi innymi właściwościami w głównej encji. Oznacza to, że Twoja nieruchomość będzie gotowa do uzyskania dostępu: została już odebrana. Podmiot nie będzie musiał ponownie wysyłać zapytań do bazy danych, ponieważ uzyskujesz dostęp do tej właściwości.

Nazywa się to niecierpliwie ładowaniem.

Moja opinia :

Częściej wybieram chętnie ładowanie (nie-wirtualne), ponieważ przez większość czasu potrzebuję każdej własności każdego obiektu do użycia bez konieczności odpytywania (szybciej, jeśli naprawdę chcesz wszystko szybko), ale jeśli masz dostęp do tej właściwości tylko raz na jakiś czas (nie wymieniając niczego) i częściej chcesz tylko resztę informacji wyłączyć TEGO, a następnie uczynić ją wirtualną, aby ta właściwość nie spowolniła reszty zapytania tylko dla kilku dostępów.

Mam nadzieję, że to było jasne ...

Przykłady:

Gdzie NIE używałbym wirtualnie (niecierpliwie):

foreach(var line in query)
{
    var v = line.NotVirtual; // I access the property for every line
}

Gdzie chciałbym użyć wirtualnego lub leniwego ładowania:

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
}

Ostatnia rzecz :

Jeśli nie zapytasz o ponad 1000 linii bazy danych, to cokolwiek wybierzesz, nie będzie miało dużego efektu. Możesz także zadeklarować te właściwości jako wirtualne, a jeśli chcesz przetestować na odwrót, po prostu musisz to zrobić:

context.LazyLoadingEnabled = false;

Spowoduje to anulowanie efektu wirtualnego.

Edytować 

W przypadku nowszych wersji EF:

WhateverEntities db = new WhateverEntities() 
db.Configuration.LazyLoadingEnabled = false;

12
2018-01-26 19:27





W EF Core wybrał domyślnie ścieżkę zniechęcającą do leniwego ładowania. Uważam również, że ta funkcja nie została jeszcze zaimplementowana po tym wydaniu.

https://github.com/aspnet/EntityFramework/issues/3312

W poprzednich wersjach EF wirtualne właściwości nawigacji pozwalały na leniwy ładunek powiązanych obiektów.

Przypuszczam, że ładowanie właściwości nawigacyjnych na razie można osiągnąć tylko za pomocą .Include(...)

EDYTOWAĆ:

Istnieje kilka sposobów ładowania powiązanych obiektów obsługiwanych w Core. Jeśli jesteś zainteresowany: https://docs.microsoft.com/en-us/ef/core/querying/related-data


3
2018-01-26 19:20





Aktualizacja: wstępna implementacja leniwego ładowania, zaplanowana dla EF Core 2.1, będzie wymagać, aby właściwości nawigacji były deklarowane jako wirtualne. Widzieć https://github.com/aspnet/EntityFrameworkCore/issues/10787, a ogólniej, aby śledzić postępy w leniwym ładowaniu, zobacz https://github.com/aspnet/EntityFrameworkCore/issues/10509.


1
2018-02-05 22:42