109 votes

la propriété de navigation devrait être virtuelle - non requise dans le noyau ef ?

Comme je m'en 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 ne le voient 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 ?

143voto

Ivan Stoev Points 1156

virtual n'a jamais été requis dans EF. Il n'est nécessaire que si vous voulez le support du chargement paresseux.

Desde Le chargement paresseux n'est pas encore supporté par EF Core. actuellement virtual n'ont pas de signification particulière. Il le sera lorsque (et si) ils ajouteront le support du chargement paresseux (il y a une plan pour le faire).

Mise à jour : À partir de EF Core 2.1, Chargement paresseux est désormais pris en charge. Mais dès que vous n'ajoutez pas Microsoft.EntityFrameworkCore.Proxies et l'activer via UseLazyLoadingProxies la réponse initiale reste valable.

Toutefois, si vous le faites, les choses changent totalement en raison de l'absence de contrôle de l'option d'adhésion dans la mise en œuvre initiale - elle nécessite tous 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 qu'il soit réparé. Si vous avez vraiment besoin d'un chargement paresseux, utilisez l'alternative suivante Chargement paresseux sans proxies dans ce cas, à nouveau virtual n'a pas d'importance.

0 votes

S'il n'a pas de signification particulière, pourquoi l'échafaudage génère-t-il chaque propriété de navigation avec virtuel ?

1 votes

@CamiloTerevinto Juste au cas où ? Par défaut ? Cela n'a plus vraiment d'importance maintenant.

0 votes

Très intéressant, en fait, j'aimerais savoir si ce sont des virtuels par défaut pour EF core, je ne pense pas.

31voto

Antoine Pelletier Points 1733

Le mot clé virtuel n'a jamais été OBLIGATOIRE... Il est facultatif.

Qu'est-ce que cela 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. Elle sera récupérée de la base de données UNIQUEMENT si vous essayez d'y accéder, ou d'accéder à l'un de ses composants.

C'est ce qu'on 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 pas besoin d'interroger à nouveau la base de données parce que vous accédez à cette propriété.

C'est ce qu'on appelle le chargement rapide.

Mon avis :

Le plus souvent, je choisis le chargement rapide (non virtuel) parce que la plupart du temps, j'ai besoin que chaque propriété de chaque entité soit utilisée sans avoir à faire une nouvelle requête (plus rapide dans le cas où vous voulez vraiment que tout soit rapide) mais si vous n'accédez à cette propriété qu'une fois de temps en temps (vous ne listez rien) et que vous voulez plus souvent juste le reste des informations excepté CETTE propriété, alors rendez-la virtuelle pour que cette propriété ne ralentisse pas le reste de la requête juste pour quelques accès.

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

Exemples :

Où je n'utiliserais PAS le virtuel (Eagerly) :

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

Où j'utiliserais 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, le choix que vous ferez n'aura pas un grand effet. De plus, vous pouvez déclarer ces propriétés virtuelles et si vous voulez tester l'inverse, il vous suffit de faire ceci (Entity 4.0) :

context.LazyLoadingEnabled = false;

Cela annulera l'effet virtuel.

Modifier

Pour les versions plus récentes de EF :

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

26voto

Matt Points 874

Les choses ont changé depuis la rédaction de la réponse acceptée. En 2018, Le chargement paresseux 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 proxies, ce qui implique que les propriétés que l'on souhaite charger paresseusement doivent être définies avec la commande virtual . Pour citer la page liée :

La façon la plus simple d'utiliser le chargement paresseux est d'installer le paquet Microsoft.EntityFrameworkCore.Proxies et de l'activer en appelant la fonction UseLazyLoadingProxies . [EF Core activera alors le chargement paresseux pour toute propriété de navigation qui peut être surchargée - c'est-à-dire qu'elle doit être virtuelle et sur une classe dont on peut hériter.

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 faire du Lazy Loading sans proxy, qui consiste à injecter ILazyLoader dans le constructeur du type de données. Ceci est expliqué ici .

En résumé, il y a deux façons d'effectuer un chargement paresseux : avec et sans mandataires. virtual es requis si et seulement si vous souhaitez prendre en charge le chargement paresseux avec les proxies. Sinon, ce n'est pas le cas.

0 votes

Les choses ont changé, mais le point de ma réponse est toujours valable - les propriétés de navigation sont toujours pas nécessaire sauf que vous vous mettez dans une situation où ils sont nécessaire en raison d'une fonctionnalité incomplète publiée. Lorsque le chargement paresseux avec les proxies sera corrigé, votre réponse sera invalidée, et de nouveau virtual ne sera pas nécessaire comme il se doit.

0 votes

@IvanStoev Alors comment se fait-il que j'ai cherché exactement cela, parce que EF6 essayait d'insérer et de "lier" des entités dans une collection enfant, alors que le mot-clé virtual a instantanément fait comprendre à EF6 que les entités dans la collection peuvent être autonomes et donc n'inclure que les références à celles-ci, créant ainsi des FKs comme souhaité. J'ai un peu peur que vous ayez mal compris l'importance de ce mot-clé. Non seulement virtual permet le chargement paresseux, mais il a également résolu le problème que j'ai rencontré ci-dessus dans une application légèrement plus complexe. Je ne crois pas qu'il s'agisse d'une solution simple et rapide. n'est pas nécessaire .

0 votes

@beggarboy Ce n'est absolument PAS nécessaire. public ICollection<SomeEntity> SomeEntities { get; set; } o public SomeEntity SomeEntity { get; set; } est suffisante pour que EF détecte la propriété de navigation, donc la relation.

4voto

vasil oreshenski Points 1068

Dans EF, Core a choisi de décourager le chargement paresseux par défaut. 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 paresseusement les entités liées.

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

EDIT :

Il y a plusieurs façons de charger les entités liées qui sont supportées dans Core. Si cela vous intéresse : https://docs.microsoft.com/en-us/ef/core/querying/related-data

1voto

Speedbird186 Points 356

Mise à jour : une première implémentation du chargement paresseux, 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 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X