Pourquoi utiliser "virtual" pour les propriétés de classe dans les définitions du modèle de cadre D'entité?

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

le blog contient l'échantillon 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 l'objet de l'utilisation de virtual pour définir un bien d'une catégorie? Quel effet produit-il?

193
demandé sur jps 2011-12-17 09:44:05

5 réponses

il permet au cadre de L'entité de créer un proxy autour de la propriété virtuelle afin que la propriété 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 code POCO en premier? pour une discussion plus approfondie.

Edit pour préciser "créer un proxy autour de": En "create a proxy around" je me réfère spécifiquement à ce que le cadre de L'entité faire. Le cadre Entity exige que vos propriétés de navigation soient marquées comme étant virtuelles afin que le chargement paresseux et le suivi efficace des changements soient pris en charge. Voir exigences pour la création de procurations POCO .

Le Framework Entity utilise l'héritage pour supporter cette fonctionnalité, c'est pourquoi il exige que certaines propriétés soient marquées virtuelles dans votre classe de base POCOs. Il crée littéralement de nouveaux types qui dérivent de vos types POCO. Donc ton POCO est agir comme un type de base pour les sous-classes créées dynamiquement du cadre D'entités. C'est ce que j'ai voulu dire par "créer un mandataire".

les sous-classes créées dynamiquement que le framework Entity crée deviennent apparentes lorsque L'on utilise le Framework Entity à l'exécution, et non au moment de la compilation statique. Et seulement si vous activez les fonctions de chargement ou de suivi paresseux du Framework Entity. Si vous optez pour ne jamais utiliser les fonctions de chargement ou de suivi de changement paresseux du Framework Entity (ce qui n'est pas la valeur par défaut) alors vous n'avez pas besoin de déclarer vos propriétés de navigation comme étant virtuelles. Vous êtes alors responsable de charger vous-même ces propriétés de navigation, soit en utilisant ce que le cadre D'Entity appelle "eager loading", soit en récupérant manuellement les types liés à travers plusieurs requêtes de base de données. Vous pouvez et devez utiliser le chargement paresseux et modifier les caractéristiques de suivi pour vos propriétés de navigation dans de nombreux scénarios cependant.

si vous deviez créer un standalone les propriétés de classe et de marque sont virtuelles, et il suffit de construire et d'utiliser des instances de ces classes dans votre propre application, complètement en dehors de la portée du cadre de L'entité, alors vos propriétés virtuelles ne vous rapporteraient rien par elles-mêmes.

Éditer " pour décrire pourquoi propriétés devrait être marquée comme "virtuelle 1519110920"

propriétés telles que:

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

ne Sont pas des champs et ne doivent pas être considérées comme tel. 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<RSVP> get_RSVPs()
{
    return _RSVPs;
}

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

private RSVP _RSVPs;

c'est pourquoi ils sont marqués comme virtuels à utiliser dans le cadre Entity, il permet aux classes dynamiquement créées de surpasser les fonctions get et set générées en interne. Si votre propriété de navigation getter / setters fonctionne pour vous dans l'utilisation de votre Framework Entity, essayez de les réviser pour juste les propriétés, recompiler, et voir si le Entity Framework est capable de continuer à fonctionner correctement:

 public virtual ICollection<RSVP> RSVPs;
218
répondu Shan Plourde 2017-05-23 10:31:31

le mot-clé virtual dans C# permet à une méthode ou à une propriété d'être écrasée par des classes d'enfant. Pour plus d'informations veuillez vous référer à 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 la laisse ici pour quiconque cherche une réponse simple à la question originale , non descriptive.

72
répondu M.Babcock 2017-12-18 14:05:28

je comprends la frustration OPs, cet usage de virtuel n'est pas pour l'abstraction templée que le modificateur virtuel de facto est efficace pour.

si certains sont encore aux prises avec ce problème, je leur offrirais mon point de vue, car j'essaie de garder les solutions simples et le jargon au minimum:

Entity Framework dans un simple morceau n'utiliser le chargement paresseux, qui est l'équivalent de préparer quelque chose pour l'avenir de l'exécution. Qui correspond à la le modificateur 'virtuel', mais il y a plus.

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 nulle en SQL. Vous n'avez pas à rejoindre avec empressement chaque table keyed lors de l'exécution d'une requête, mais quand vous avez besoin de l'information -- il devient demande-dirigée.

j'ai également mentionné nullable parce que de nombreuses propriétés de navigation ne sont pas pertinents au début. c'est à dire À un client ou d'une commande scénario, vous n'avez pas à attendre le moment où une commande est traitée pour créer un client. Vous pouvez, mais si vous aviez un processus multi-étapes pour atteindre cet objectif, vous pourriez trouver le besoin de persister les données du client pour l'achèvement ultérieur ou pour le déploiement à des commandes futures. Si toutes les propriétés nav étaient implémentées, vous devriez établir chaque clé étrangère et chaque champ relationnel sur la sauvegarde. Cela remet vraiment les données en mémoire, ce qui va à l'encontre du rôle de persistance.

donc, bien qu'il puisse sembler cryptique dans l'exécution réelle au moment de l'exécution, j'ai trouvé la meilleure règle de base à utiliser serait: si vous produisez des données (lecture dans un modèle de vue ou un modèle Serialisable) et avez besoin de valeurs avant les références, ne pas utiliser virtuel; si votre portée recueille des données qui peuvent être incomplètes ou un besoin de recherche et ne pas exiger chaque paramètre de recherche terminée pour une recherche, le code fera bon usage de référence, similaire à l'utilisation propriétés de valeur nulles int? longue?. De plus, l'abstraction de votre logique d'entreprise à partir de votre collecte de données jusqu'à ce que le besoin de l'injecter a de nombreux avantages de performance, similaire à instancier un objet et de le démarrer à null. Le cadre de l'entité fait appel à beaucoup de réflexion et de dynamique, ce qui peut dégrader la performance, et la nécessité d'avoir un modèle flexible qui peut être adapté à la demande est essentielle à la gestion de la performance.

pour moi, cela a toujours eu plus de sens que d'utiliser une technologie surchargée jargon comme les mandataires, les délégués, les manipulateurs et autres. Une fois que vous appuyez sur votre troisième ou quatrième lang de programmation, il peut devenir brouillon avec ceux-ci.

20
répondu Nathan Teague 2015-02-19 01:15:01

il est assez courant de définir des propriétés de navigation dans un modèle pour être virtuel. Lorsqu'une propriété de navigation est définie comme virtuelle, elle peut profitez de certaines fonctionnalités du Framework Entity. Le le plus commun est chargement paresseux.

chargement paresseux est une belle caractéristique de nombreux ORMs parce qu'il vous permet pour accéder dynamiquement des données liées à un modèle. Il ne sera pas inutilement récupérer les données connexes jusqu'à ce qu'il est réellement accessible, ainsi réduire l'interrogation initiale des données de la base de données.

From book "ASP.NET MVC 5 avec Bootstrap et Knockout.js"

12
répondu Hassan Rahman 2016-03-02 07:52:38

dans le contexte de EF, le marquage d'une propriété comme 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 supplante vos propriétés virtuelles avec une implémentation qui charge l'entité référencée lorsqu'elle est consultée pour la première fois. Si vous ne marquez pas la propriété comme virtuelle, le chargement paresseux ne fonctionnera pas avec elle.

1
répondu Shakeer Hussain 2018-02-27 07:58:36