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 ssortingng Title { get; set; } public DateTime EventDate { get; set; } public ssortingng Address { get; set; } public ssortingng HostedBy { get; set; } public virtual ICollection RSVPs { get; set; } } public class RSVP { public int RsvpID { get; set; } public int DinnerID { get; set; } public ssortingng 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 a-t-il?

    Il permet à Entity Framework de créer un proxy autour de la propriété virtuelle pour que la propriété prenne en charge le chargement différé et un suivi des modifications plus efficace. 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 clarifier “créer un proxy autour de”: Par “créer un proxy autour de”, je fais spécifiquement référence à ce que fait Entity Framework. Entity Framework exige que vos propriétés de navigation soient marquées comme virtuelles afin que le chargement différé et le suivi efficace des modifications soient pris en charge. Reportez-vous à la section Configuration requirejse pour la création de proxy POCO .
    Entity Framework utilise l’inheritance pour prendre en charge cette fonctionnalité. C’est pourquoi certaines propriétés doivent être marquées comme virtuelles dans vos POCO de classe de base. Cela crée littéralement de nouveaux types dérivés de vos types POCO. Votre POCO agit donc comme un type de base pour les sous-classes créées dynamicment par Entity Framework. C’est ce que je voulais dire par “créer un proxy autour”.

    Les sous-classes créées de manière dynamic créées par Entity Framework deviennent apparentes lors de l’utilisation d’Entity Framework lors de l’exécution, et non lors de la compilation statique. Et seulement si vous activez les fonctionnalités de chargement différé ou de suivi du Entity Framework. Si vous choisissez de ne jamais utiliser les fonctionnalités de chargement différé ou de suivi des modifications de Entity Framework (ce qui n’est pas le cas par défaut), vous n’avez pas besoin de déclarer vos propriétés de navigation comme virtuelles. Vous êtes alors responsable du chargement de ces propriétés de navigation vous-même, soit en utilisant ce que Entity Framework appelle «chargement rapide», soit en récupérant manuellement les types associés dans plusieurs requêtes de firebase database. Vous pouvez et devez utiliser les fonctionnalités de chargement différé 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 scope d’Entity Framework, vos propriétés virtuelles ne vous apporteraient rien dans leur cas. posséder.

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

    Propriétés telles que:

      public ICollection RSVPs { get; set; } 

    Ne sont pas des champs et ne doivent pas être considérés comme tels. Ceux-ci 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 get_RSVPs() { return _RSVPs; } public void set_RSVPs(RSVP value) { _RSVPs = value; } private RSVP _RSVPs; 

    C’est pourquoi ils sont marqués comme virtuels pour être utilisés dans Entity Framework, ils permettent aux classes créées dynamicment de remplacer les fonctions get et set générées en interne. Si votre propriété de navigation getter / setters fonctionne pour vous dans votre utilisation Entity Framework, essayez de les modifier pour ne sélectionner que les propriétés, recomstackr et voir si Entity Framework est toujours capable de fonctionner correctement:

      public virtual ICollection RSVPs; 

    Le mot-clé virtual en C # permet à une méthode ou une propriété d’être remplacée par des classes enfant. Pour plus d’informations, reportez-vous à la documentation MSDN sur le mot clé “virtuel”

    MISE À JOUR: Il est évident que ma réponse ne correspond pas à ce qui était attendu étant donné les circonstances de la question, mais je le laisse ici pour quiconque cherche une réponse simple à la question initiale non descriptive posée.

    Je comprends la frustration des OP, cet usage du virtuel n’est pas pour l’abstraction basée sur des modèles pour laquelle le modificateur virtuel de facto est efficace.

    Si certains luttent encore contre cela, je proposerais mon sharepoint vue, alors que j’essaie de garder les solutions simples et le jargon au minimum:

    Entity Framework dans une pièce simple utilise un chargement différé, ce qui équivaut à préparer quelque chose pour une exécution future. Cela correspond au modificateur “virtuel”, mais il y a plus à 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 dans SQL. Vous NE DEVEZ PAS rejoindre chaque table avec saisie au moment où vous effectuez une requête, mais lorsque vous en avez besoin, elle devient axée sur la demande.

    J’ai également mentionné nullable car de nombreuses propriétés de navigation ne sont pas pertinentes au début. C’est-à-dire que dans un scénario client / commande, vous n’avez 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 conserver les données du client pour une exécution ultérieure ou pour un déploiement dans des commandes futures. Si toutes les propriétés de navigation ont été implémentées, vous devez établir chaque clé étrangère et chaque champ relationnel sur la sauvegarde. Cela ne fait que remettre les données en mémoire, ce qui va à l’encontre du rôle de la persistance.

    Donc, même si cela peut sembler cryptique dans l’exécution réelle au moment de l’exécution, j’ai trouvé que la meilleure règle à suivre serait: si vous produisez des données (lecture dans un modèle de vue ou modèle sérialisable) et que vous avez besoin de valeurs avant utiliser le virtuel; Si votre étendue collecte des données qui peuvent être incomplètes ou un besoin de recherche et ne nécessite pas que tous les parameters de recherche soient complétés pour une recherche, le code fera un bon usage de référence, similaire à l’utilisation de propriétés de valeur nullable int? longue?. De plus, en extrayant votre logique métier de votre collection de données jusqu’à ce que vous ayez besoin de l’injecter, vous bénéficiez de nombreux avantages, comme l’instanciation d’un object et son lancement à null. Entity Framework utilise beaucoup de reflection et de dynamic, ce qui peut dégrader les performances, et la nécessité de disposer d’un modèle flexible pouvant s’adapter à la demande est essentielle à la gestion des performances.

    Pour moi, cela avait toujours plus de sens que d’utiliser un jargon technologique surchargé comme les procurations, les delegates, les gestionnaires, etc. Une fois que vous avez atteint votre troisième ou quasortingème langage de programmation, cela peut être compliqué.

    Il est assez courant de définir les propriétés de navigation dans un modèle pour qu’elles soient virtuelles. Lorsqu’une propriété de navigation est définie comme étant virtuelle, elle peut tirer parti de certaines fonctionnalités d’Entity Framework. Le plus commun est le chargement paresseux.

    Le chargement différé est une fonctionnalité intéressante de nombreux ORM, car il vous permet d’accéder de manière dynamic aux données associées à partir d’un modèle. Il ne récupérera pas inutilement les données associées jusqu’à ce qu’elles soient réellement accédées, réduisant ainsi l’interrogation initiale des données de la firebase database.

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

    Dans le contexte de EF, le marquage d’une propriété comme virtuel permet à EF d’utiliser le chargement différé pour le charger. Pour que le chargement différé fonctionne, EF doit créer un object proxy qui remplace vos propriétés virtuelles avec une implémentation qui charge l’entité référencée lors de son premier access. Si vous ne marquez pas la propriété comme virtuelle, le chargement paresseux ne fonctionnera pas avec elle.