Ereditarietà TPH della finestra di progettazione

Questa procedura dettagliata illustra come implementare l'ereditarietà della tabella per gerarchia (TPH) nel modello concettuale con Entity Framework Designer (EF Designer). L'ereditarietà TPH usa una tabella di database per gestire i dati per tutti i tipi di entità in una gerarchia di ereditarietà.

In questa procedura dettagliata verrà eseguito il mapping della tabella Person a tre tipi di entità: Person (il tipo di base), Student (deriva da Person) e Instructor (deriva da Person). Si creerà un modello concettuale dal database (Database First) e quindi si modificherà il modello per implementare l'ereditarietà TPH usando Entity Framework Designer.

È possibile eseguire il mapping a un'ereditarietà TPH usando Model First, ma è necessario scrivere un flusso di lavoro di generazione di database personalizzato, complesso. È quindi necessario assegnare questo flusso di lavoro alla proprietà Flusso di lavoro di generazione database in Entity Framework Designer. Un'alternativa più semplice consiste nell'usare Code First.

Altre opzioni di ereditarietà

Table-per-Type (TPT) è un altro tipo di ereditarietà in cui vengono mappate tabelle separate nel database alle entità che partecipano all'ereditarietà.  Per informazioni su come eseguire il mapping dell'ereditarietà di tabelle per tipo con Entity Framework Designer, vedere Ereditarietà TPT di Ef Designer.

I modelli di ereditarietà dei tipi concreti (TPC) e di ereditarietà mista sono supportati dal runtime di Entity Framework, ma non sono supportati da Entity Designer. Se si vuole usare TPC o ereditarietà mista, sono disponibili due opzioni: usare Code First o modificare manualmente il file EDMX. Se si sceglie di usare il file EDMX, la finestra Dettagli mapping verrà attivata in modalità provvisoria e non sarà possibile usare la finestra di progettazione per modificare i mapping.

Prerequisiti

Per completare questa procedura dettagliata, sarà necessario:

  • Una versione recente di Visual Studio.
  • Database di esempio School.

Configurare il progetto

  • Aprire Visual Studio 2012.
  • Selezionare File -> Nuovo -> Progetto
  • Nel riquadro sinistro fare clic su Visual C#, quindi selezionare il modello console .
  • Immettere TPHDBFirstSample come nome.
  • Seleziona OK.

Create a Model (Creare un modello)

  • Fare clic con il pulsante destro del mouse sul nome del progetto in Esplora soluzioni e scegliere Aggiungi -> Nuovo elemento.
  • Selezionare Dati dal menu a sinistra e quindi selezionare ADO.NET Entity Data Model nel riquadro Modelli.
  • Immettere TPHModel.edmx per il nome del file e quindi fare clic su Aggiungi.
  • Nella finestra di dialogo Scegli contenuto modello selezionare Genera dal database e quindi fare clic su Avanti.
  • Fare clic su Nuovo Connessione ion. Nella finestra di dialogo Proprietà Connessione ion immettere il nome del server ( ad esempio (localdb)\mssqllocaldb), selezionare il metodo di autenticazione, digitare School per il nome del database e quindi fare clic su OK. La finestra di dialogo Choose Your Data Connessione ion viene aggiornata con l'impostazione di connessione al database.
  • Nella finestra di dialogo Scegli oggetti di database selezionare la tabella Person nel nodo Tabelle.
  • Fare clic su Fine.

Viene visualizzato Entity Designer, che fornisce un'area di progettazione per la modifica del modello. Tutti gli oggetti selezionati nella finestra di dialogo Scegli oggetti di database vengono aggiunti al modello.

Questo è il modo in cui la tabella Person cerca nel database.

Person Table 

Implementare l'ereditarietà di tabelle per gerarchia

La tabella Person contiene la colonna Discriminator , che può avere uno dei due valori: "Student" e "Instructor". A seconda del valore, la tabella Person verrà mappata all'entità Student o all'entità Instructor . La tabella Person include anche due colonne, HireDate e EnrollmentDate, che devono essere nullable perché una persona non può essere uno studente e un insegnante contemporaneamente (almeno non in questa procedura dettagliata).

Aggiungere nuove entità

  • Aggiungere una nuova entità. A tale scopo, fare clic con il pulsante destro del mouse su uno spazio vuoto dell'area di progettazione di Entity Framework Designer e scegliere Aggiungi-entità>.
  • Digitare Instructor per il nome dell'entità e selezionare Person nell'elenco a discesa per il tipo di base.
  • Fare clic su OK.
  • Aggiungere un'altra nuova entità. Digitare Student per entity name (Studente) per Entity name (Nome entità) e selezionare Person (Persona) nell'elenco a discesa per Il tipo di base.

Nell'area di progettazione sono stati aggiunti due nuovi tipi di entità. Una freccia punta dai nuovi tipi di entità al tipo di entità Person . Ciò indica che Person è il tipo di base per i nuovi tipi di entità.

  • Fare clic con il pulsante destro del mouse sulla proprietà HireDate dell'entità Person . Selezionare Taglia (o usare il tasto CTRL+X).
  • Fare clic con il pulsante destro del mouse sull'entità Instructor e scegliere Incolla (o usare ctrl-V).
  • Fare clic con il pulsante destro del mouse sulla proprietà HireDate e scegliere Proprietà.
  • Nella finestra Proprietà impostare la proprietà Nullable su false.
  • Fare clic con il pulsante destro del mouse sulla proprietà EnrollmentDate dell'entità Person . Selezionare Taglia (o usare il tasto CTRL+X).
  • Fare clic con il pulsante destro del mouse sull'entità Student e selezionare Incolla(o usare il tasto CTRL+V).
  • Selezionare la proprietà EnrollmentDate e impostare la proprietà Nullable su false.
  • Selezionare il tipo di entità Persona . Nella finestra Proprietà impostarne la proprietà Abstract su true.
  • Eliminare la proprietà Discriminator da Person. Il motivo per cui deve essere eliminato è illustrato nella sezione seguente.

Eseguire il mapping delle entità

  • Fare clic con il pulsante destro del mouse su Instructor e scegliere Mapping tabella. L'entità Instructor è selezionata nella finestra Dettagli mapping.

  • Fare clic su <Aggiungi tabella o vista> nella finestra Dettagli mapping. Il <campo Aggiungi tabella o vista> diventa un elenco a discesa di tabelle o viste a cui è possibile eseguire il mapping dell'entità selezionata.

  • Selezionare Persona dall'elenco a discesa.

  • La finestra Dettagli mapping viene aggiornata con mapping di colonna predefiniti e un'opzione per l'aggiunta di una condizione.

  • Fare clic su <Aggiungi una condizione>. Il <campo Aggiungi condizione> diventa un elenco a discesa di colonne per cui è possibile impostare le condizioni.

  • Selezionare Discriminator nell'elenco a discesa.

  • Nella colonna Operatore della finestra Dettagli mapping selezionare = dall'elenco a discesa.

  • Nella colonna Valore/Proprietà digitare Instructor. Il risultato finale dovrebbe essere simile al seguente:

    Mapping Details

  • Ripetere questi passaggi per il tipo di entità Student , ma rendere la condizione uguale al valore Student .
    Il motivo per cui volevamo rimuovere la proprietà Discriminator è che non è possibile eseguire il mapping di una colonna di tabella più volte. Questa colonna verrà usata per il mapping condizionale, pertanto non può essere usata anche per il mapping delle proprietà. L'unico modo in cui può essere usato per entrambi, se una condizione usa un confronto Is Null o Is Not Null .

A questo punto l'ereditarietà tabella per gerarchia risulta implementata.

Final TPH

Usare il modello

Aprire il file Program.cs in cui è definito il metodo Main . Incollare il codice seguente nella funzione Main . Il codice esegue tre query. La prima query riporta tutti gli oggetti Person . La seconda query usa il metodo OfType per restituire gli oggetti Instructor . La terza query usa il metodo OfType per restituire gli oggetti Student .

    using (var context = new SchoolEntities())
    {
        Console.WriteLine("All people:");
        foreach (var person in context.People)
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Instructors only: ");
        foreach (var person in context.People.OfType<Instructor>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }

        Console.WriteLine("Students only: ");
        foreach (var person in context.People.OfType<Student>())
        {
            Console.WriteLine("    {0} {1}", person.FirstName, person.LastName);
        }
    }