2009-09-22 25 views
8

penso che c'è un post simile qui di questo, ma non è esattamente la stessa cosa ...Entity Framework - Ereditarietà con .Include?

ho due entità nel mio modello EF - chiamiamoli Persona e Developer, con quest'ultimo che eredita dalla precedente.

Ho anche un'associazione sullo sviluppatore chiamata Qualifiche. Questo non è visibile sull'entità Person.

Se sto scrivendo una query sul contesto, come faccio a .Includere() le qualifiche dello sviluppatore, ad es.

dal dipendente in context.Employee .include ("Qualifiche") selezionare dipendente

non funziona ... EF si lamenta che il rapporto non esiste (presumo perché non esiste su Dipendente - ma non esiste un'entità Developer nel contesto, solo Employee).

risposta

0

Non ho familiarità con EF ma questo mi sembra un problema di ereditarietà standard. Se si desidera accedere alle proprietà univoche di una classe figlia da una raccolta di oggetti "padre" (in cui gli oggetti reali possono o meno essere istanze della classe figlio), è necessario controllare il tipo di oggetto e trasmetterlo al figlio se appropriato, quindi è possibile accedere alle proprietà uniche.

Cosa ti aspetteresti che la dichiarazione data restituisse se alcuni o tutti gli oggetti fossero persone non sviluppatrici?

+0

Hi ... Non dovrebbe provare a caricare le entità figlio per la classe base, perché non esistono. Faccio il casting per controllare le proprietà del bambino ecc. - ma l'intero punto dell'inserimento è di leggerlo tutto in una volta sola (tenete presente che EF non supporta il caricamento pigro). –

+0

Penso che sarei incline a non sottoclasse la Persona, ma piuttosto a creare un'altra classe chiamata Sviluppatore che ha-una Persona, in questo modo puoi probabilmente recuperare una raccolta di Person e tramite l'associazione essere in grado di recuperare quelli a cui fa riferimento uno Sviluppatore e da tale oggetto Developer essere in grado di trovare quelli con qualifiche. Non sono davvero sicuro che sia possibile fare ciò che stai cercando di fare usando la gerarchia delle classi che hai indicato. – Lazarus

2

ne dite di questo:

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

Per le cose sono interessanti qui:

  1. siamo esclusi i dipendenti che non sono sviluppatori
  2. stiamo proiettando poi le loro qualifiche, e come un effetto collaterale di tale proiezione, qualcosa chiamato fixup con riempimento ogni sviluppatore . Anche le valutazioni. Cioè questo è un altro modo per ottenere lo stesso effetto di Include().

se successivamente si esegue questa operazione:

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

Si otterrà solo gli sviluppatori, e avranno le loro qualifiche caricata troppo.

Vedi Tip 1 per ulteriori informazioni sul motivo per cui questo funziona

Spero che questo aiuti

Alex

+0

Ciao - grazie per il suggerimento. Lo proverò! Sembra un po 'come se questa non fosse una soluzione "ufficialmente supportata" da quel collegamento che hai fornito. L'ho trovato temporaneamente chiamando Load nella collezione figlio, ma questo si traduce in una chiamata SQL separata, quindi sono desideroso di evitarlo se possibile. Grazie ancora. –

+1

Anche se una cosa che ho appena capito - il metodo in cui vive questo codice dovrebbe essere in grado di lavorare con classi derivate e non derivate, cioè dovrei recuperare una collezione di dipendenti, di cui alcuni potrebbero essere sviluppatori (chi dovrebbe quindi avere le loro qualifiche compilate). –

+1

Il bit che non è ufficialmente supportato sul collegamento era l'ordinamento della raccolta. Il caricamento effettivo della raccolta (tutto ciò che viene utilizzato sopra) è completamente supportato. –

10

ho incontrato questo problema e sperimentato un po '. Ecco cosa ho trovato funzionato usando LINQ 2 Entity.

Supponiamo di avere nel tuo esempio Persona < - Sviluppatore ---- Qualifiche.

Se si desidera selezionare uno sviluppatore con le qualifiche incluse, lo si farebbe.

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

Ora lascia dire che abbiamo un altro associazione tra persona e indirizzo, possiamo includere anche indirizzo nel selezionare anche utilizzando LINQ 2 Entity.

Nota come ho incluso le cose di cui avevo bisogno prima ho convertito il Tipo e anche incluso di nuovo dopo la conversione. Entrambe le versioni dovrebbero ora lavorare insieme senza problemi. Ho testato questi metodi e funzionano entrambi. Spero che funzionino per te visto che hai impostato correttamente l'ereditarietà.

GL.

2

in base alla risposta del Tri Q, ma per quelli che preferiscono l'approccio '.load()', è possibile utilizzare:

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

Io lo uso nel mio DbContext. Ho creato il metodo LoadDb(), che carica tutti i dati di cui ho bisogno. Quindi posso usarlo da molti progetti.

Problemi correlati