Partager via


Procédure pas à pas : mappage de l'héritage - TPH (table par hiérarchie)

Cette rubrique indique comment implémenter l'héritage TPH (table par hiérarchie) en modifiant le modèle conceptuel dans un modèle EDM (Entity Data Model). L'héritage TPH (table par hiérarchie) utilise une table de base de données pour gérer les données de tous les types d'entités d'une hiérarchie d'héritage. Pour plus d'informations sur l'implémentation de l'héritage avec un modèle EDM, voir Héritage (EDM).

Dans cette procédure pas à pas, vous allez implémenter l'héritage TPH (table par hiérarchie) en modifiant le modèle EDM utilisé dans l'application CourseManager (pour plus d'informations, voir la section Composants requis, plus loin dans cette rubrique).

Dans le modèle EDM CourseManager, le type d'entité Person a deux propriétés, HireDate et EnrollmentDate, qui peuvent appartenir à de nouveaux types d'entités (Instructor et Student, respectivement) qui héritent de Person. Les étapes suivantes récapitulent l'implémentation de l'héritage TPH (table par hiérarchie) dans ce cas. Les procédures de cette procédure pas à pas fournissent plus de détails.

  1. Créez deux nouveaux types d'entités, Instructor et Student.

  2. Définissez Person comme type de base pour chaque nouveau type d'entité.

  3. Déplacez la propriété HireDate de Person vers Instructor et déplacez la propriété EnrollmentDate de Person vers Student.

  4. Transformez le type d'entité Person en type abstrait.

  5. Mappez le type d'entité Instructor à la table Person avec deux conditions : HireDate Is Not Null et EnrollmentDate Is Null.

  6. Mappez le type d'entité Student à la table Person avec deux conditions : EnrollmentDate Is Not Null et HireDate Is Null.

Configuration requise

Pour effectuer cette procédure pas à pas, vous devez créer l'application CourseManager. Pour plus d'informations et d'instructions, voir le Démarrage rapide d'Entity Framework. Après avoir généré cette application, vous allez modifier son modèle EDM en implémentant l'héritage TPH (table par hiérarchie). Vous étendrez ensuite les fonctionnalités de l'application pour afficher l'inscription à un cours sélectionné.

NoteRemarque

Étant donné qu'un grand nombre des rubriques de procédure pas à pas de cette documentation utilisent l'application CourseManager comme point de départ, nous vous recommandons d'utiliser une copie de l'application CourseManager pour cette procédure pas à pas, plutôt que de modifier le code CourseManager d'origine.

Cette procédure pas à pas suppose que le lecteur a des compétences de base avec Visual Studio, le .NET Framework et la programmation en Visual C# ou en Visual Basic.

Implémentation de l'héritage TPH (table par hiérarchie)

Dans cette procédure, vous allez modifier la partie conceptuelle du modèle EDM SchoolModel pour implémenter l'héritage TPH (table par hiérarchie).

Pour implémenter l'héritage TPH (table par hiérarchie)

  1. Ouvrez la solution CourseManager dans Visual Studio.

  2. Dans l'Explorateur de solutions, double-cliquez sur le fichier School.edmx.

    Le fichier School.edmx s'ouvre dans ADO.NET Entity Data Model Designer (Concepteur d'entités).

  3. Cliquez avec le bouton droit sur un espace vide de l'aire de conception du Concepteur d'entités, pointez sur Ajouter, puis cliquez sur Entité.

    La boîte de dialogue Nouvelle entité s'affiche.

  4. Tapez Instructor comme Nom du Entity, puis sélectionnez Person dans la liste déroulante correspondant au Type de base.

  5. Cliquez sur OK.

    Un nouveau type d'entité est créé et affiché sur l'aire de conception.

  6. Répétez les étapes 3 à 5, mais tapez Student comme Nom du Entity à la deuxième étape.

    Vous avez maintenant deux nouveaux types d'entités, Instructor et Student, affichés sur l'aire de conception. Les flèches pointent depuis les nouveaux types d'entités vers le type d'entité Person, ce qui indique que Person est le type de base des nouveaux types d'entités.

  7. Cliquez avec le bouton droit sur la propriété HireDate (sous Propriétés scalaires) du type d'entité Person. Sélectionnez Couper.

  8. Cliquez avec le bouton droit sur Propriétés scalaires du type d'entité Instructor, puis sélectionnez Coller.

  9. Cliquez avec le bouton droit sur la propriété HireDate, puis sélectionnez Propriétés.

  10. Dans la fenêtre Propriétés, affectez à la propriété Nullable la valeur false.

  11. Répétez les étapes 7 à 10, mais coupez la propriété EnrollmentDate du type d'entité Person, puis collez-la dans le type d'entité Student.

  12. Sélectionnez le type d'entité Person. Dans la fenêtre Propriétés, affectez à la propriété Abstract la valeur true.

    Un message s'affiche, indiquant que la définition d'un type d'entité comme abstrait supprimera tous les mappages de fonction existants pour ce type. Cliquez sur OK.

    NoteRemarque

    En général, il n'est pas nécessaire d'utiliser des types abstraits pour modéliser des scénarios TPH (table par hiérarchie). Les types abstraits sont utilisés dans cet exemple pour illustrer leur utilisation dans un modèle EDM.

    NoteRemarque

    Le reste de cette procédure requiert la fenêtre Détails de Mapping. Si cette fenêtre n'est pas visible, cliquez avec le bouton droit sur l'aire de conception, puis sélectionnez Détails de Mapping.

  13. Sélectionnez le type d'entité Instructor, puis cliquez sur <Ajouter une table ou une vue> dans la fenêtre Détails de Mapping.

    Le champ <Ajouter une table ou une vue> devient une liste déroulante de tables ou de vues auxquelles l'entité sélectionnée peut être mappée.

  14. Sélectionnez Person dans la liste déroulante.

    La fenêtre Détails de Mapping est mise à jour avec les mappages de colonnes par défaut et une option permettant l'ajout d'une condition.

  15. Cliquez sur <Ajouter un Condition>.

    Le champ <Ajouter un Condition> devient une liste déroulante des colonnes pour lesquelles des conditions peuvent être définies.

  16. Sélectionnez HireDate dans la liste déroulante.

    Un autre champ <Ajouter un Condition> apparaît.

  17. Dans la colonne Opérateur de la fenêtre Détails de Mapping, sélectionnez Is dans la liste déroulante.

  18. Dans la colonne Propriété/Valeur, sélectionnez Non Null.

  19. Cliquez sur <Ajouter un Condition>.

  20. Sélectionnez EnrollmentDate dans la liste déroulante.

  21. Dans la colonne Opérateur, sélectionnez Is dans la liste déroulante.

  22. Dans la colonne Propriété/Valeur, sélectionnez Null.

    NoteRemarque

    Si une valeur/propriété est utilisée dans une condition, elle ne peut pas également être une propriété d'entité, sauf si la condition utilise une comparaison Is Null ou Is Not Null.

  23. Répétez les étapes 13 à 22 pour le type d'entité Student, mais rendez les conditions HireDate Is Null et EnrollmentDate Is Not Null.

L'héritage TPH (table par hiérarchie) est maintenant implémenté.

Création de l'interface utilisateur

Ensuite, vous allez ajouter un bouton au formulaire CourseViewer que charge et affiche le formulaire Enrollment. Puis vous allez ajouter deux contrôles ComboBox et un contrôle ListBox au formulaire Enrollment. Le premier ComboBox vous permet de sélectionner un service. Le deuxième ComboBox vous permet de sélectionner un cours en fonction du service sélectionné dans le premier ComboBox. Une liste d'étudiants et d'enseignants pour le cours sélectionné est affichée dans le contrôle ListBox.

Pour créer l'interface utilisateur

  1. Cliquez avec le bouton droit sur le projet CourseManager dans l'Explorateur de solutions, pointez sur Ajouter, puis sélectionnez Nouvel élément.

    La boîte de dialogue Ajouter un nouvel élément s'affiche.

  2. Sélectionnez Windows Form, affectez, au nom du formulaire, Enrollment.vb ou Enrollment.cs (en fonction du langage que vous utilisez), puis cliquez sur Ajoutez.

    Un nouveau formulaire est ajouté au projet et s'ouvre dans le concepteur de formulaires. Le nom du formulaire a la valeur Enrollment et le texte a la valeur Enrollment.

  3. Faites glisser un contrôle ComboBox de la boîte à outils vers le formulaire, puis affectez-lui departmentList comme nom dans la fenêtre Propriétés.

  4. Faites glisser un autre contrôle ComboBox vers le formulaire, puis affectez-lui courseList comme nom.

  5. Faites glisser un contrôle Listbox de la boîte à outils vers le formulaire. Affectez-lui studentList comme nom dans la fenêtre Propriétés.

  6. Dans l'Explorateur de solutions, double-cliquez sur CourseViewer.cs ou sur CourseViewer.vb.

    Le mode Création du formulaire CourseViewer apparaît.

  7. Faites glisser un contrôle Button de la boîte à outils vers le formulaire CourseViewer.

  8. Dans la fenêtre Propriétés, définissez viewEnrollment comme nom du bouton et définissez View Enrollment comme texte du bouton.

  9. Double-cliquez sur le bouton viewEnrollment.

    Le fichier code-behind du formulaire CourseViewer s'ouvre.

  10. Ajoutez le code suivant au gestionnaire d'événements viewEnrollment_click :

    Dim enrollmentForm As New Enrollment()
    enrollmentForm.Visible = True
    
    Enrollment enrollmentForm = new Enrollment();
    enrollmentForm.Visible = true;
    

L'interface utilisateur est maintenant terminée.

Interrogation du modèle EDM

Dans cette procédure, vous allez interroger le modèle EDM et lier les résultats à des contrôles Windows Forms. Pour plus d'informations sur la liaison d'objets à des contrôles, voir Liaison d'objets à des contrôles (Entity Framework).

Pour interroger le modèle EDM

  1. Le formulaire Enrollment étant ouvert dans le concepteur de formulaires, double-cliquez sur ce formulaire Enrollment.

    Le fichier code-behind du formulaire Enrollment s'ouvre.

  2. Ajoutez les instructions using (C#) ou Imports (Visual Basic) suivantes pour référencer l'espace de noms EDM.

    Imports System.Data.Objects
    Imports System.Data.Objects.DataClasses
    
    using System.Data.Objects;
    using System.Data.Objects.DataClasses;
    
  3. Ajoutez une propriété à la classe Enrollment qui représente le contexte de données :

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities
    
    // Create an ObjectContext instance based on SchoolEntity.
    private SchoolEntities schoolContext;
    
  4. Dans le gestionnaire d'événements Enrollment_Load, ajoutez du code pour initialiser le contexte de l'objet et lier le contrôle ComboBox à une requête qui retourne tous les services et les informations relatives aux cours associés.

    ' Initialize the ObjectContext.
    schoolContext = New SchoolEntities()
    
    ' Define a query that returns all Department objects and 
    ' related Course objects, ordered by name.
    Dim departmentQuery As ObjectQuery(Of Department) = _
        schoolContext.Department.Include("Course") _
        .OrderBy("it.Name")
    
    ' Bind the ComboBox control to the query, which is 
    ' executed during data binding.
    Me.departmentList.DataSource = departmentQuery _
    .Execute(MergeOption.OverwriteChanges)
    Me.departmentList.DisplayMember = "Name"
    
        // Initialize the ObjectContext.
        schoolContext = new SchoolEntities();
    
        // Define a query that returns all Department objects
        // and related Course objects, ordered by name.
        ObjectQuery<Department> departmentQuery =
            schoolContext.Department.Include("Course")
                                    .OrderBy("it.Name");
    
        // Bind the ComboBox control to the query, which is
        // executed during data binding.
        this.departmentList.DataSource = departmentQuery
    .Execute(MergeOption.OverwriteChanges);
        this.departmentList.DisplayMember = "Name";
    
  5. Repassez en mode création du formulaire Enrollment, puis double-cliquez sur le contrôle ComboBoxdepartmentList.

    Le gestionnaire d'événements departmentList_SelectedIndexChanged est créé dans le fichier code-behind.

  6. Ajoutez du code au gestionnaire d'événements pour lier le contrôle ComboBoxcourseList aux propriétés Course du Department sélectionné.

    ' Get the object for the selected department
    Dim department As Department = CType(Me.departmentList _
            .SelectedItem, Department)
    
    ' Bind the ComboBox control Course properties of
    ' the selected Department.
    courseList.DataSource = department.Course
    courseList.DisplayMember = "Title"
    
    // Get the object for the selected department.
    Department department =
            (Department)this.departmentList.SelectedItem;
    
    // Bind the ComboBox control Course properties of 
    // the selected Department.
    courseList.DataSource = department.Course;
    courseList.DisplayMember = "Title";
    
  7. Repassez en mode création du formulaire Enrollment, puis double-cliquez sur le contrôle ComboBoxcourseList.

    Le gestionnaire d'événements courseList_SelectedIndexChanged est créé dans le fichier code-behind.

  8. Ajoutez du code au gestionnaire d'événements pour afficher une liste d'étudiants dans l'objet ListBox.

    Me.studentList.Items.Clear()
    
    ' Get the CourseID from the selected Course.
    Dim course As Course = CType(Me.courseList.SelectedItem,  _
         Course)
    Dim courseId As Integer = course.CourseID
    
    ' Get all CourseGrade objects for the supplied CourseID
    Dim studentQuery As Course = schoolContext.Course.Where _
         ("it.CourseID = @courseID", New ObjectParameter _
          ("courseID", courseId)).Include("CourseGrade"). _
          FirstOrDefault()
    
    ' Get all students for each CourseGrade
    For Each cg As CourseGrade In studentQuery.CourseGrade
        cg.PersonReference.Load()
        studentList.Items.Add(cg.Person.LastName + ", " + _
                            cg.Person.FirstName)
    Next
    
    studentList.Items.Add(" ")
    
    ' Get all Instructor types for the supplied CourseID
    Dim instructorQuery As Course = schoolContext.Course. _
         Where("it.CourseID = @courseID", New ObjectParameter _
               ("courseID", courseId)).Include("Person") _
               .FirstOrDefault()
    
    ' Display each instructor for the specified Course
    For Each Instructor As Instructor In instructorQuery.Person
        Me.studentList.Items.Add("Instructor: " + Instructor. _
                        LastName + ", " + Instructor.FirstName)
    Next
    
    studentList.Items.Clear();
    
    // Get the CourseID from the selected Course.
    Course course = (Course)courseList.SelectedItem;
    int courseId = course.CourseID;
    
    // Get all CourseGrade types for the supplied CourseID
    Course studentQuery = schoolContext.Course.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("CourseGrade").
            FirstOrDefault();
    
    // Get all students for each CourseGrade
    foreach (CourseGrade cg in studentQuery.CourseGrade)
    {
        cg.PersonReference.Load();
        studentList.Items.Add(cg.Person.LastName + ", " +
            cg.Person.FirstName);
    }
    
    studentList.Items.Add(" ");
    
    // Get all Instructor types for the supplied CourseID
    Course instructorQuery = schoolContext.Course.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("Person").
            FirstOrDefault();
    
    // Display each instructor for the specified course.
    foreach (Instructor instructor in instructorQuery.Person.
        OfType<Instructor>())
    {
        studentList.Items.Add("Instructor: " + instructor.
            LastName + ", " + instructor.FirstName);
    }
    

L'application est maintenant terminée. Appuyez sur Ctrl+F5 pour l'exécuter. Cliquez sur le bouton View Enrollment pour charger le formulaire Enrollment. L'inscription au cours et les enseignants pour le cours sélectionné sont affichés dans le ListBox.

Liste de codes

Cette section répertorie la version finale du fichier code-behind pour le formulaire Enrollment.

Imports System.Data.Objects
Imports System.Data.Objects.DataClasses

Public Class Enrollment

    ' Create an ObjectContext instance based on SchoolEntity.
    Private schoolContext As SchoolEntities

    Private Sub Enrollment_Load(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) Handles MyBase.Load
        ' Initialize the ObjectContext.
        schoolContext = New SchoolEntities()

        ' Define a query that returns all Department objects and 
        ' related Course objects, ordered by name.
        Dim departmentQuery As ObjectQuery(Of Department) = _
            schoolContext.Department.Include("Course") _
            .OrderBy("it.Name")

        ' Bind the ComboBox control to the query, which is 
        ' executed during data binding.
        Me.departmentList.DataSource = departmentQuery _
        .Execute(MergeOption.OverwriteChanges)
        Me.departmentList.DisplayMember = "Name"
    End Sub

    Private Sub departmentList_SelectedIndexChanged(ByVal sender _
            As System.Object, ByVal e As System.EventArgs) Handles _
            departmentList.SelectedIndexChanged
        ' Get the object for the selected department
        Dim department As Department = CType(Me.departmentList _
                .SelectedItem, Department)

        ' Bind the ComboBox control Course properties of
        ' the selected Department.
        courseList.DataSource = department.Course
        courseList.DisplayMember = "Title"
    End Sub

    Private Sub courseList_SelectedIndexChanged(ByVal sender As  _
            System.Object, ByVal e As System.EventArgs) Handles _
            courseList.SelectedIndexChanged
        Me.studentList.Items.Clear()

        ' Get the CourseID from the selected Course.
        Dim course As Course = CType(Me.courseList.SelectedItem,  _
             Course)
        Dim courseId As Integer = course.CourseID

        ' Get all CourseGrade objects for the supplied CourseID
        Dim studentQuery As Course = schoolContext.Course.Where _
             ("it.CourseID = @courseID", New ObjectParameter _
              ("courseID", courseId)).Include("CourseGrade"). _
              FirstOrDefault()

        ' Get all students for each CourseGrade
        For Each cg As CourseGrade In studentQuery.CourseGrade
            cg.PersonReference.Load()
            studentList.Items.Add(cg.Person.LastName + ", " + _
                                cg.Person.FirstName)
        Next

        studentList.Items.Add(" ")

        ' Get all Instructor types for the supplied CourseID
        Dim instructorQuery As Course = schoolContext.Course. _
             Where("it.CourseID = @courseID", New ObjectParameter _
                   ("courseID", courseId)).Include("Person") _
                   .FirstOrDefault()

        ' Display each instructor for the specified Course
        For Each Instructor As Instructor In instructorQuery.Person
            Me.studentList.Items.Add("Instructor: " + Instructor. _
                            LastName + ", " + Instructor.FirstName)
        Next
    End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;

namespace CourseManager
{
    public partial class Enrollment : Form
    {
        // Create an ObjectContext instance based on SchoolEntity.
        private SchoolEntities schoolContext;

        public Enrollment()
        {
            InitializeComponent();
        }

        private void Enrollment_Load(object sender, EventArgs e)
        {
            // Initialize the ObjectContext.
            schoolContext = new SchoolEntities();

            // Define a query that returns all Department objects
            // and related Course objects, ordered by name.
            ObjectQuery<Department> departmentQuery =
                schoolContext.Department.Include("Course")
                                        .OrderBy("it.Name");

            // Bind the ComboBox control to the query, which is
            // executed during data binding.
            this.departmentList.DataSource = departmentQuery
        .Execute(MergeOption.OverwriteChanges);
            this.departmentList.DisplayMember = "Name";
        }

        private void departmentList_SelectedIndexChanged(object sender, 
            EventArgs e)
        {
            // Get the object for the selected department.
            Department department =
                    (Department)this.departmentList.SelectedItem;

            // Bind the ComboBox control Course properties of 
            // the selected Department.
            courseList.DataSource = department.Course;
            courseList.DisplayMember = "Title";
        }

        private void courseList_SelectedIndexChanged(object sender, 
            EventArgs e)
        {
            studentList.Items.Clear();

            // Get the CourseID from the selected Course.
            Course course = (Course)courseList.SelectedItem;
            int courseId = course.CourseID;

            // Get all CourseGrade types for the supplied CourseID
            Course studentQuery = schoolContext.Course.Where(
                "it.CourseID = @courseID", new ObjectParameter
                    ("courseID", courseId)).Include("CourseGrade").
                    FirstOrDefault();

            // Get all students for each CourseGrade
            foreach (CourseGrade cg in studentQuery.CourseGrade)
            {
                cg.PersonReference.Load();
                studentList.Items.Add(cg.Person.LastName + ", " +
                    cg.Person.FirstName);
            }

            studentList.Items.Add(" ");

            // Get all Instructor types for the supplied CourseID
            Course instructorQuery = schoolContext.Course.Where(
                "it.CourseID = @courseID", new ObjectParameter
                    ("courseID", courseId)).Include("Person").
                    FirstOrDefault();

            // Display each instructor for the specified course.
            foreach (Instructor instructor in instructorQuery.Person.
                OfType<Instructor>())
            {
                studentList.Items.Add("Instructor: " + instructor.
                    LastName + ", " + instructor.FirstName);
            }
        } 
    }
}

Étapes suivantes

Vous avez implémenté avec succès l'héritage TPH (table par hiérarchie) dans un modèle EDM. Pour plus d'informations sur la définition d'un modèle EDM avec l'héritage TPH (table par hiérarchie), voir Procédure : définir un modèle avec l'héritage TPH (table par hiérarchie) (Entity Framework). Pour plus d'informations sur la création d'applications avec Entity Framework, voir Guide de programmation (Entity Framework).

Voir aussi

Autres ressources

Scénarios ADO.NET Entity Data Model Designer
Tâches des outils Entity Data Model