web-dev-qa-db-fra.com

propriété de navigation doit être virtuelle - non requise dans ef core?

Comme je me souviens dans EF la propriété de navigation doit être virtuelle :

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

Mais je regarde EF Core et je ne le vois pas comme virtuel:

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

N'est-il plus nécessaire?

40
Alexan

virtual n'a jamais été requis dans EF. Ce n'était nécessaire que si vous voulez un support de chargement paresseux.

Depuis le chargement différé n'est pas encore pris en charge par EF Core , actuellement virtual n'a aucune signification particulière. Ce serait quand (et si) ils ajouteraient un support de chargement paresseux (il y a un plan pour le faire).

Mise à jour: À partir de EF Core 2.1, Chargement différé est maintenant pris en charge. Mais dès que vous n'ajoutez pas Microsoft.EntityFrameworkCore.Proxies et l'activez via UseLazyLoadingProxies, la réponse d'origine s'applique toujours.

Cependant, si vous le faites, les choses changent totalement en raison de l'absence de contrôle d'opt-in dans la mise en œuvre initiale - it Requiert all vos propriétés de navigation doivent être virtual. Ce qui n'a aucun sens pour moi, vous feriez mieux de ne pas l'utiliser jusqu'à ce que tout soit réparé. Si vous avez vraiment besoin d'un chargement paresseux, utilisez la méthode alternative Chargement paresseux sans mandataires , auquel cas là encore virtual n'a pas d'importance.

62
Ivan Stoev

Les choses ont changé depuis que la réponse acceptée a été écrite. En 2018, Le chargement différé est désormais pris en charge à partir d'Entity Framework Core 2.1 pour deux approches différentes.

La méthode la plus simple consiste à utiliser des serveurs proxy, ce qui nécessitera que les propriétés souhaitées soient chargées paresseusement pour être définies avec virtual. Pour citer depuis la page liée:

Le moyen le plus simple d'utiliser le chargement différé consiste à installer le package Microsoft.EntityFrameworkCore.Proxies et à l'activer avec un appel à UseLazyLoadingProxies. [...] EF Core activera ensuite le chargement paresseux pour toute propriété de navigation pouvant être remplacée, c'est-à-dire qu'elle doit être virtuelle et sur une classe pouvant être héritée.

Et voici l'exemple de code fourni:

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

Il existe un autre moyen de charger la charge sans proxy, qui consiste à injecter ILazyLoader dans le constructeur du type de données. Ceci est expliqué ici .

En bref, il existe deux manières d'effectuer le chargement différé: avec et sans proxy. virtual est obligatoire si et seulement si vous souhaitez prendre en charge le chargement différé avec des serveurs proxy. Sinon, ce n'est pas.

18
Matt

Clé virtuelle Word n'a jamais été REQUIS ... C'est facultatif.

Qu'est-ce que ça change?

1. Si vous déclarez votre propriété virtuelle:

Votre propriété virtuelle (par défaut) ne sera pas chargée immédiatement lors de l'interrogation de l'objet principal. Il sera récupéré de la base de données UNIQUEMENT si vous essayez d'y accéder ou si vous accédez à l'un de ses composants.

Et cela s'appelle le chargement paresseux.

2. Si vous le déclarez non virtuel:

Votre propriété sera (par défaut) chargée immédiatement avec toutes les autres propriétés de votre entité principale. Cela signifie que votre propriété sera prête à accéder: elle a déjà été récupérée. L'entité n'aura plus à interroger la base de données car vous accédez à cette propriété.

C'est ce qu'on appelle charger avec impatience.

Mon avis:

Plus souvent, je choisis de charger avec impatience (non-virtuel), car la plupart du temps, il faut que chaque propriété de chaque entité soit utilisée sans avoir à interroger en arrière (plus rapidement dans le cas où vous voulez vraiment tout rapidement), mais si vous accédez à cette propriété de temps en temps (vous n’affiche rien) et vous voulez plus souvent que le reste des informations, sauf CE, puis le rendre virtuel afin que cette propriété ne ralentisse pas le reste de la requête pour quelques accès seulement.

J'espère que c'était clair ...

Exemples:

Où je ne voudrais pas utiliser virtuel (avec impatience):

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

Où je voudrais utiliser le chargement virtuel ou paresseux:

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
}

une dernière chose :

Si vous n'interrogez pas plus de 1 000 lignes d'une base de données, votre choix n'aura pas d'effet important. En outre, vous pouvez déclarer ces propriétés virtuelles et si vous voulez tester l’inverse, il vous suffit de le faire (Entity 4.0):

context.LazyLoadingEnabled = false;

Cela annulera l'effet virtuel.

Éditer

Pour les nouvelles versions de EF:

WhateverEntities db = new WhateverEntities() 
db.Configuration.LazyLoadingEnabled = false;
16
Antoine Pelletier

En EF, Core a choisi par défaut de dissuader le chargement paresseux. Aussi, je pense que cette fonctionnalité n'est toujours pas implémentée suite à ce problème.

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

Avec les versions précédentes de EF, les propriétés de navigation virtuelle permettaient de charger paresseux les entités associées.

Je suppose que le chargement des propriétés de navigation pour le moment ne peut être réalisé qu'avec .Include(...)

MODIFIER:

Il existe plusieurs façons de charger des entités associées qui sont prises en charge dans Core. Si vous êtes intéressé: https://docs.Microsoft.com/en-us/ef/core/querying/related-data

3
vasil oreshenski

Mise à jour: une implémentation initiale du chargement différé, prévue pour EF Core 2.1, nécessitera que les propriétés de navigation soient déclarées virtuelles. Voir https://github.com/aspnet/EntityFrameworkCore/issues/10787 , et plus généralement pour suivre les progrès du chargement paresseux, voir https://github.com/aspnet/EntityFrameworkCore/issues/10509 .

1
SvenAelterman