Share via


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

Cette rubrique indique comment implémenter l'héritage TPH (table par hiérarchie) en modifiant le modèle conceptuel défini dans un fichier .edmx. 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.

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

Dans le modèle conceptuel 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, consultez le Démarrage rapide d'Entity Framework. Après avoir généré cette application, vous implémenterez l'héritage TPH (table par hiérarchie) en modifiant son modèle conceptuel et les mappages. Vous étendrez ensuite les fonctionnalités de l'application pour afficher l'inscription à un cours sélectionné.

Cc716683.note(fr-fr,VS.100).gifRemarque :
É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 modifierez SchoolModel pour implémenter l'héritage TPH (table par hiérarchie). Pour regarder une présentation vidéo de la procédure suivante, consultez Comment faire pour définir un modèle avec l'héritage TPH (table par hiérarchie) à l'aide des outils Entity Framework (en anglais).

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.

    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 conceptuel.

    Cc716683.note(fr-fr,VS.100).gifRemarque :
    Le reste de cette procédure requiert la fenêtre Détails de mappage.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.

    Cc716683.note(fr-fr,VS.100).gifRemarque :
    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 définissez les conditions HireDate Is Null et EnrollmentDate Is Not Null.

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

Création d'une association entre Formateur et OfficeAssignment

De cette section, vous modifierez l'association entre Personne et OfficeAssignment afin qu'elle devienne une association entre Formateur et OfficeAssignment. La modification de l'association de cette façon est cohérente avec l'intention du modèle.

Pour créer une association entre Formateur et OfficeAssignment

  1. Cliquez avec le bouton droit sur l'association entre Person et OfficeAssignment, puis sélectionnez Supprimer.

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

  3. Pour une terminaison de l'association, sélectionnez Instructor dans la liste déroulante Entité et sélectionnez 1 (Un) dans la liste déroulante Multiplicité.

  4. Pour l'autre terminaison de l'association, sélectionnez OfficeAssignment dans la liste déroulante Entité et sélectionnez 0..1 (Zéro ou Un) dans la liste déroulante Multiplicité.

  5. Cliquez sur OK.

  6. Cliquez avec le bouton droit sur l'association entre Instructor et OfficeAssignment, puis sélectionnez Propriétés.

  7. Dans la fenêtre Propriétés, cliquez sur Contrainte référentielle, puis sur le bouton de sélection (...) qui s'affiche dans la colonne de valeur.

    La boîte de dialogue Contrainte référentielle s'affiche.

  8. Sélectionnez Instructor dans la liste déroulante Principal.

  9. Cliquez sur OK.

Vous avez maintenant ajouté une association entre Instructor et OfficeAssignment.

Création de l'interface utilisateur

Ensuite, vous allez ajouter un bouton au formulaire CourseViewer qui 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 conceptuel

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

Pour interroger le modèle conceptuel

  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 :

    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 SchoolEntities.
    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.Departments.Include("Courses") _
              .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.Departments.Include("Courses")
                                .OrderBy("it.Name");
    
    // Bind the ComboBox control to the query.
    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 ComboBox departmentList.

    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 ComboBox courseList 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.Courses
    courseList.DisplayMember = "Title"
    
    // Get the object for the selected department.
    Department department =
            (Department)this.departmentList.SelectedItem;
    
    // Bind the ComboBox control to the Course  
    // properties of the selected Department.
    courseList.DataSource = department.Courses;
    courseList.DisplayMember = "Title";
    
  7. Repassez en mode création du formulaire Enrollment, puis double-cliquez sur le contrôle ComboBox courseList.

    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 StudentGrade objects for the supplied CourseID
    Dim studentQuery As Course = schoolContext.Courses.Where _
         ("it.CourseID = @courseID", New ObjectParameter _
          ("courseID", courseId)).Include("StudentGrades"). _
          FirstOrDefault()
    
    ' Get all students for each StudentGrade
    For Each cg As StudentGrade In studentQuery.StudentGrades
        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.Courses. _
         Where("it.CourseID = @courseID", New ObjectParameter _
               ("courseID", courseId)).Include("People") _
               .FirstOrDefault()
    
    ' Display each instructor for the specified Course
    For Each Instructor As Instructor In instructorQuery.People
        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 StudentGrade types for the supplied CourseID
    Course studentQuery = schoolContext.Courses.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("StudentGrades").
            FirstOrDefault();
    
    // Get all students for each StudentGrade
    foreach (StudentGrade sg in studentQuery.StudentGrades)
    {
        sg.PersonReference.Load();
        studentList.Items.Add(sg.Person.LastName + ", " +
            sg.Person.FirstName);
    }
    
    studentList.Items.Add(" ");
    
    // Get all Instructor types for the supplied CourseID
    Course instructorQuery = schoolContext.Courses.Where(
        "it.CourseID = @courseID", new ObjectParameter
            ("courseID", courseId)).Include("People").
            FirstOrDefault();
    
    // Display each instructor for the specified course.
    foreach (Instructor instructor in instructorQuery.People.
        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.Departments.Include("Courses") _
            .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.Courses
        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 StudentGrade objects for the supplied CourseID
        Dim studentQuery As Course = schoolContext.Courses.Where _
             ("it.CourseID = @courseID", New ObjectParameter _
              ("courseID", courseId)).Include("StudentGrades"). _
              FirstOrDefault()

        ' Get all students for each StudentGrade
        For Each cg As StudentGrade In studentQuery.StudentGrades
            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.Courses. _
             Where("it.CourseID = @courseID", New ObjectParameter _
                   ("courseID", courseId)).Include("People") _
                   .FirstOrDefault()

        ' Display each instructor for the specified Course
        For Each Instructor As Instructor In instructorQuery.People
            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 SchoolEntities.
        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.Departments.Include("Courses")
                                        .OrderBy("it.Name");

            // Bind the ComboBox control to the query.
            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 to the Course  
            // properties of the selected Department.
            courseList.DataSource = department.Courses;
            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 StudentGrade types for the supplied CourseID
            Course studentQuery = schoolContext.Courses.Where(
                "it.CourseID = @courseID", new ObjectParameter
                    ("courseID", courseId)).Include("StudentGrades").
                    FirstOrDefault();

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

            studentList.Items.Add(" ");

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

            // Display each instructor for the specified course.
            foreach (Instructor instructor in instructorQuery.People.
                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 conceptuel. Pour plus d'informations sur la définition d'un modèle conceptuel avec l'héritage TPH (table par hiérarchie), consultez How to: Define a Model with Table-per-Hierarchy Inheritance. Pour plus d'informations sur la création d'applications avec Entity Framework, consultez ADO.NET Entity Framework.

Voir aussi

Autres ressources

Scénarios Entity Data Model Tools
Tâches Entity Data Model Tools