2009-09-22 9 views
8

Je pense qu'il y a un article similaire sur ce sujet mais pas exactement pareil ...Entity Framework - Héritage avec .Include?

J'ai deux entités dans mon modèle EF - appelons-les Person et Developer, ce dernier héritant de l'ancien. J'ai également une association sur le développeur appelé Qualifications. Ceci n'est pas visible sur l'entité Personne.

Si j'écris une requête par rapport au contexte, comment puis-je automatiquement inclure() les qualifications du développeur, par ex.

de l'employé dans context.Employee .include (« qualifications ») employé sélectionnez

ne fonctionne pas ... EF se plaint que la relation n'existe pas (je suppose parce qu'il n'existe pas sur Employee - mais il n'y a pas d'entité Developer sur le contexte, juste Employee).

Répondre

0

Je ne suis pas familier avec EF mais cela me semble être un problème d'héritage standard. Si vous souhaitez accéder aux propriétés uniques d'une classe enfant à partir d'une collection d'objets 'parents' (où les objets réels peuvent ou non être des instances de la classe enfant), vous devez vérifier le type d'objet et le transmettre à l'enfant le cas échéant, vous pouvez accéder aux propriétés uniques.

À quoi s'attendriez-vous que l'instruction donnée renvoie si certains ou tous les objets étaient des personnes non développeurs?

+0

Salut ... Il ne devrait pas essayer de charger dans les entités enfants pour la classe de base, car ils n'existent pas. Je fais le casting pour vérifier les propriétés de l'enfant etc. - mais le but de l'inclusion est de tout lire en une seule fois (gardez à l'esprit que EF ne supporte pas le chargement paresseux). –

+0

Je pense que je serais enclin à ne pas sous-classer la personne mais plutôt créer une autre classe appelée Développeur qui a une personne, de cette façon vous pouvez probablement récupérer une collection de personne et par association être en mesure de récupérer ceux qui sont référencés par un développeur et à partir de cet objet Developer être en mesure de trouver ceux avec des qualifications. Je ne suis vraiment pas sûr qu'il soit possible de faire ce que vous essayez de faire en utilisant la hiérarchie de classe que vous avez indiquée. – Lazarus

2

Que diriez-vous ceci:

var results = from developer in ctx.Employee.OfType<Developer>() 
       select new {developer, Qualifications = developer.Qualifications}; 

Pour les choses sont intéressantes ici:

  1. nous excluons les employés qui ne sont pas développeurs
  2. nous projetons ensuite leurs qualifications et comme un effet secondaire de cette projection, quelque chose appelé correctif avec remplir chaque développeur.Qualifications aussi. C'est à dire. ceci est une autre façon d'obtenir le même effet que Include() .

si vous faites ensuite ceci:

var developers = from anon in developers.AsEnumerable() 
       select anon.Developer; 

Vous obtiendrez seulement les développeurs, et ils auront leurs qualifications chargé aussi.

Voir Tip 1 pour plus d'informations sur la raison pour laquelle cela fonctionne

Hope this helps

Alex

+0

Salut - merci pour la suggestion. Je vais essayer ça! Cela semble un peu comme si ce n'est pas une solution "officiellement supportée" mais à partir de ce lien que vous avez fourni, cependant. Je l'ai contourné temporairement en appelant Load sur la collection enfant, mais cela entraîne un appel SQL distinct, donc je tiens à l'éviter si possible. Merci encore. –

+1

Bien qu'une chose que je viens de réaliser - la méthode dans laquelle ce code vit doit pouvoir travailler avec des classes dérivées et non dérivées à savoir je devrais récupérer une collection d'employés, dont certains peuvent être des développeurs (qui devraient alors avoir leurs qualifications remplies). –

+1

Le bit qui n'est pas officiellement pris en charge sur le lien était le tri de la collection. Le chargement réel de la collection (tout ce qui est utilisé ci-dessus) est entièrement pris en charge. –

10

Je suis tombé sur ce problème et expérimenté un peu. Voici ce que j'ai trouvé travaillé en utilisant LINQ 2 Entity.

Disons que nous avons dans votre exemple Personne < - Développeur ---- Qualifications.

Si vous souhaitez sélectionner un développeur avec les qualifications incluses, vous le feriez.

var dev = (from d in context.Persons.OfType<Developer> 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Maintenant, supposons que nous avons une autre association entre personne et adresse, nous pouvons également inclure l'adresse dans la sélection aussi LINQ 2 Entité.

var dev = (from d in context.Persons 
          .Include("Address") 
          .OfType<Developer>() 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Remarquez comment j'ai inclus les éléments dont j'avais besoin avant de convertir le Type et de l'inclure à nouveau après la conversion. Les deux comprend maintenant devraient travailler ensemble sans aucun problème. J'ai testé ces méthodes et elles fonctionnent toutes les deux. J'espère qu'ils travaillent pour vous étant donné que vous avez correctement configuré votre héritage.

GL.

2

Sur la base de la réponse de Tri Q, mais pour ceux qui préfèrent l'approche '.load()', vous pouvez utiliser:

context.Persons.OfType<Developer>().Include(t => t.Qualifications).Load(); 

Je l'utilise dans mon DbContext. J'ai créé la méthode LoadDb(), qui charge toutes les données dont j'ai besoin. Je peux donc l'utiliser dans de nombreux projets.