266 votes

Pourquoi utiliser 'virtual' pour les propriétés de classe dans les définitions de modèle Entity Framework ?

Dans le blog suivant : http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

Le blog contient l'exemple de code suivant :

public class Dinner
{
   public int DinnerID { get; set; }
   public string Title { get; set; }
   public DateTime EventDate { get; set; }
   public string Address { get; set; }
   public string HostedBy { get; set; }
   public virtual ICollection<RSVP> RSVPs { get; set; }
}

public class RSVP
{
   public int RsvpID { get; set; }
   public int DinnerID { get; set; }
   public string AttendeeEmail { get; set; }
   public virtual Dinner Dinner { get; set; }
}

Quel est le but de l'utilisation de virtual lors de la définition d'une propriété dans une classe ? Quel effet cela a-t-il ?

10 votes

Voulez-vous comprendre l'objectif général du mot-clé "virtual" en C# ou comment il se rapporte spécifiquement à Entity Framework ?

4 votes

@M.Babcock : Je demande quel est le but en ce qui concerne les propriétés, car je n'ai jamais vu cela auparavant.

1 votes

Si vous êtes familier avec la façon dont le mot-clé virtual affecte le polymorphisme dans les méthodes, il en va de même pour les propriétés.

289voto

Shan Plourde Points 4631

Il permet à Entity Framework de créer un proxy autour de la propriété virtuelle afin que celle-ci puisse supporter un chargement paresseux et un suivi plus efficace des changements. Voir Quel(s) effet(s) le mot-clé virtuel peut-il avoir dans Entity Framework 4.1 POCO Code First ? pour une discussion plus approfondie.

Modifier pour préciser "créer un proxy autour" : Par "créer un proxy autour", je fais spécifiquement référence à ce que fait l'Entity Framework. L'Entity Framework exige que vos propriétés de navigation soient marquées comme virtuelles afin que le chargement paresseux et le suivi efficace des changements soient supportés. Voir Conditions requises pour la création de mandataires POCO .
L'Entity Framework utilise l'héritage pour prendre en charge cette fonctionnalité, c'est pourquoi il exige que certaines propriétés soient marquées comme virtuelles dans les POCO de votre classe de base. Il crée littéralement de nouveaux types qui dérivent de vos types POCO. Votre POCO agit donc comme un type de base pour les sous-classes créées dynamiquement par Entity Framework. C'est ce que je voulais dire par "créer un proxy autour".

Les sous-classes créées dynamiquement par l'Entity Framework deviennent apparentes lors de l'utilisation de l'Entity Framework au moment de l'exécution, et non au moment de la compilation statique. Et seulement si vous activez les fonctionnalités de chargement paresseux ou de suivi des modifications de l'Entity Framework. Si vous choisissez de ne jamais utiliser les fonctionnalités de chargement paresseux ou de suivi des modifications de l'Entity Framework (ce qui n'est pas le cas par défaut), vous n'avez pas besoin de déclarer l'une de vos propriétés de navigation comme virtuelle. Vous êtes alors responsable du chargement de ces propriétés de navigation vous-même, soit en utilisant ce que l'Entity Framework appelle le "chargement rapide", soit en récupérant manuellement les types associés à travers plusieurs requêtes de base de données. Cependant, vous pouvez et devez utiliser les fonctions de chargement paresseux et de suivi des modifications pour vos propriétés de navigation dans de nombreux scénarios.

Si vous deviez créer une classe autonome et marquer les propriétés comme virtuelles, et simplement construire et utiliser des instances de ces classes dans votre propre application, complètement en dehors de la portée de l'Entity Framework, alors vos propriétés virtuelles ne vous apporteraient rien par elles-mêmes.

Modifier pour décrire pourquoi les propriétés seraient marquées comme virtuelles

Des propriétés telles que :

 public ICollection<RSVP> RSVPs { get; set; }

ne sont pas des champs et ne doivent pas être considérés comme tels. Ils sont appelés getters et setters, et au moment de la compilation, ils sont convertis en méthodes.

//Internally the code looks more like this:
public ICollection<RSVP> get_RSVPs()
{
    return _RSVPs;
}

public void set_RSVPs(RSVP value)
{
    _RSVPs = value;
}

private RSVP _RSVPs;

C'est pourquoi elles sont marquées comme virtuelles pour être utilisées dans Entity Framework ; cela permet aux classes créées dynamiquement de remplacer les classes générées en interne. get y set fonctions. Si vos getter/setters de propriété de navigation fonctionnent pour vous dans votre utilisation d'Entity Framework, essayez de les réviser pour qu'ils ne soient que des propriétés, recompilez et voyez si l'Entity Framework est capable de continuer à fonctionner correctement :

 public virtual ICollection<RSVP> RSVPs;

4 votes

Que voulez-vous dire par "créer un proxy autour" ? Que se passe-t-il réellement ici ?

3 votes

Bonjour Gary, j'ai révisé ma réponse pour préciser ce que j'entends par "créer un proxy autour". J'espère que cela vous aidera un peu.

3 votes

Dire "les propriétés... ne sont pas des propriétés" n'est pas très utile. Toutes les propriétés sont implémentées comme des méthodes getter et/ou setter, donc cela n'a aucun sens de dire "cette propriété est en réalité une méthode getter et setter et non une propriété".

77voto

M.Babcock Points 10653

El virtual en C# permet à une méthode ou une propriété d'être surchargée par des classes filles. Pour plus d'informations, veuillez vous référer à la documentation MSDN sur le mot-clé "virtual".

MISE À JOUR : Cela ne répond pas à la question telle qu'elle a été posée, mais je la laisse ici pour tous ceux qui cherchent une réponse simple à la question de l'accès à l'information. <a href="https://stackoverflow.com/revisions/8542864/1">original </a>, question non descriptive posée.

25 votes

@Hooch ce n'est pas marqué comme correct parce que ce qui est considéré comme "correct" ne dépend pas seulement du titre de la question. J'imagine que la plupart des gens, moi et le PO inclus, traitent d'abord les questions suivantes virtual via Entity Framework - même si ce n'est pas explicite dans le titre de l'OP. La réponse acceptée est ainsi parce qu'elle touche à l'aspect Entity Framework des choses, et comment/pourquoi virtual sont utilisées dans ce contexte.

0 votes

En fait, comme le titre n'est plus actuel, n'importe quel lecteur cherchera ici une explication purement "virtuelle".

25voto

Nathan Teague Points 11

Je comprends la frustration de l'OP, cette utilisation du virtuel n'est pas pour l'abstraction modélisée pour laquelle le modificateur virtuel de facto est efficace.

Si certains d'entre vous ont encore des difficultés à cet égard, je vous propose mon point de vue, car j'essaie de garder les solutions simples et le jargon au minimum :

Entity Framework utilise le chargement paresseux, ce qui revient à préparer quelque chose pour une exécution future. Cela correspond au modificateur "virtuel", mais il y a plus que cela.

Dans Entity Framework, l'utilisation d'une propriété de navigation virtuelle vous permet de la désigner comme l'équivalent d'une clé étrangère nullable en SQL. Il n'est pas nécessaire de joindre rapidement toutes les tables à clé lors d'une requête, mais lorsque vous avez besoin de l'information, celle-ci est déterminée par la demande.

J'ai également mentionné nullable parce que de nombreuses propriétés de navigation ne sont pas pertinentes au départ. Par exemple, dans un scénario client / commandes, vous ne devez pas attendre le moment où une commande est traitée pour créer un client. Vous pouvez le faire, mais si vous aviez un processus en plusieurs étapes pour y parvenir, vous pourriez avoir besoin de persister les données du client pour les compléter ultérieurement ou pour les déployer sur de futures commandes. Si toutes les propriétés de la navigation étaient mises en œuvre, il faudrait établir chaque clé étrangère et chaque champ relationnel lors de la sauvegarde. Cela ne fait que remettre les données en mémoire, ce qui va à l'encontre du rôle de la persistance.

Ainsi, bien que cela puisse sembler cryptique dans l'exécution réelle au moment de l'exécution, j'ai constaté que la meilleure règle empirique à utiliser est la suivante : si vous produisez des données (lecture dans un modèle de vue ou un modèle sérialisable) et que vous avez besoin de valeurs avant les références, n'utilisez pas de virtuel ; si votre champ d'application recueille des données qui peuvent être incomplètes ou si vous avez besoin de rechercher et de ne pas exiger que chaque paramètre de recherche soit complété pour une recherche, le code fera bon usage de la référence, de manière similaire à l'utilisation de propriétés de valeur nullable int ? long ? De même, l'abstraction de votre logique métier de votre collecte de données jusqu'à ce que vous ayez besoin de l'injecter présente de nombreux avantages en termes de performances, comme l'instanciation d'un objet et son démarrage à null. Entity Framework utilise beaucoup de réflexion et de dynamique, ce qui peut dégrader les performances, et la nécessité de disposer d'un modèle flexible qui peut s'adapter à la demande est essentielle pour gérer les performances.

Pour moi, cela a toujours été plus logique que d'utiliser un jargon technique surchargé comme les proxies, les délégués, les gestionnaires et autres. Une fois que vous avez atteint votre troisième ou quatrième langue de programmation, cela peut devenir compliqué.

18voto

Kaka Gee Points 19

Il est assez fréquent de définir des propriétés de navigation dans un modèle pour être virtuelles. Lorsqu'une propriété de navigation est définie comme virtuelle, elle peut profiter de certaines fonctionnalités d'Entity Framework. La plus courante, la plus courante est le chargement paresseux.

Le chargement paresseux est une fonctionnalité intéressante de nombreux ORM car il vous permet de d'accéder dynamiquement aux données connexes d'un modèle. Il ne va pas inutilement inutilement les données connexes jusqu'à ce qu'elles soient effectivement consultées, ce qui réduisant ainsi l'interrogation initiale des données de la base de données.

Extrait du livre "ASP.NET MVC 5 avec Bootstrap et Knockout.js".

18voto

Shakeer Hussain Points 554

Dans le contexte de EF, le fait de marquer une propriété en tant que virtuel permet à EF d'utiliser le chargement paresseux pour le charger. Pour que le chargement paresseux fonctionne, EF doit créer un objet proxy qui surcharge vos propriétés virtuelles avec une implémentation qui charge l'entité référencée lors du premier accès. Si vous ne marquez pas la propriété comme virtuelle, le chargement paresseux ne fonctionnera pas avec elle.

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