Partager via


Prise en main avec Entity Framework 4.0 Database First et ASP.NET 4 Web Forms - Partie 5

par Tom Dykstra

L’exemple d’application web Contoso University montre comment créer des applications ASP.NET Web Forms à l’aide d’Entity Framework 4.0 et de Visual Studio 2010. Pour plus d’informations sur la série de tutoriels, consultez le premier tutoriel de la série

Dans le tutoriel précédent, vous avez commencé à utiliser le EntityDataSource contrôle pour utiliser des données associées. Vous avez affiché plusieurs niveaux de hiérarchie et modifié des données dans les propriétés de navigation. Dans ce tutoriel, vous allez continuer à travailler avec des données associées en ajoutant et en supprimant des relations et en ajoutant une nouvelle entité qui a une relation avec une entité existante.

Vous allez créer une page qui ajoute des cours attribués aux services. Les services existent déjà, et lorsque vous créez un nouveau cours, vous établissez en même temps une relation entre celui-ci et un service existant.

Capture d’écran de la fenêtre Internet Explorer, qui montre la vue Ajouter des cours avec les champs de texte ID, Titre et Crédits, ainsi qu’une liste déroulante Département.

Vous allez également créer une page qui fonctionne avec une relation plusieurs-à-plusieurs en affectant un instructeur à un cours (en ajoutant une relation entre deux entités que vous sélectionnez) ou en supprimant un instructeur d’un cours (en supprimant une relation entre deux entités que vous sélectionnez). Dans la base de données, l’ajout d’une relation entre un instructeur et un cours entraîne l’ajout d’une nouvelle ligne à la table d’association ; la CourseInstructor suppression d’une relation implique la suppression d’une ligne de la table d’association CourseInstructor . Toutefois, vous effectuez cette opération dans Entity Framework en définissant des propriétés de navigation, sans faire référence à la CourseInstructor table explicitement.

Capture d’écran de la fenêtre Internet Explorer, qui montre la vue Affecter des instructeurs aux cours ou Supprimer des cours.

Ajout d’une entité avec une relation à une entité existante

Créez une page web nommée CoursesAdd.aspx qui utilise la page Site.Master master et ajoutez le balisage suivant au Content contrôle nommé Content2:

<h2>Add Courses</h2>
    <asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EntitySetName="Courses" 
        EnableInsert="True" EnableDelete="True" >
    </asp:EntityDataSource>
    <asp:DetailsView ID="CoursesDetailsView" runat="server" AutoGenerateRows="False"
        DataSourceID="CoursesEntityDataSource" DataKeyNames="CourseID"
        DefaultMode="Insert" oniteminserting="CoursesDetailsView_ItemInserting">
        <Fields>
            <asp:BoundField DataField="CourseID" HeaderText="ID" />
            <asp:BoundField DataField="Title" HeaderText="Title" />
            <asp:BoundField DataField="Credits" HeaderText="Credits" />
            <asp:TemplateField HeaderText="Department">
                <InsertItemTemplate>
                    <asp:EntityDataSource ID="DepartmentsEntityDataSource" runat="server" ConnectionString="name=SchoolEntities"
                        DefaultContainerName="SchoolEntities" EnableDelete="True" EnableFlattening="False"
                        EntitySetName="Departments" EntityTypeFilter="Department">
                    </asp:EntityDataSource>
                    <asp:DropDownList ID="DepartmentsDropDownList" runat="server" DataSourceID="DepartmentsEntityDataSource"
                        DataTextField="Name" DataValueField="DepartmentID"
                        oninit="DepartmentsDropDownList_Init">
                    </asp:DropDownList>
                </InsertItemTemplate>
            </asp:TemplateField>
            <asp:CommandField ShowInsertButton="True" />
        </Fields>
    </asp:DetailsView>

Ce balisage crée un EntityDataSource contrôle qui sélectionne les cours, qui permet l’insertion et qui spécifie un gestionnaire pour l’événement Inserting . Vous allez utiliser le gestionnaire pour mettre à jour la propriété de navigation lors de la Department création d’une Course entité.

Le balisage crée également un DetailsView contrôle à utiliser pour ajouter de nouvelles Course entités. Le balisage utilise des champs liés pour les propriétés d’entité Course . Vous devez entrer la CourseID valeur, car il ne s’agit pas d’un champ d’ID généré par le système. Au lieu de cela, il s’agit d’un numéro de cours qui doit être spécifié manuellement lors de la création du cours.

Vous utilisez un champ de modèle pour la Department propriété de navigation, car les propriétés de navigation ne peuvent pas être utilisées avec BoundField des contrôles. Le champ modèle fournit une liste déroulante pour sélectionner le service. La liste déroulante est liée à l’ensemble d’entités à l’aide Departments de Eval , à nouveau, Bindcar vous ne pouvez pas lier directement les propriétés de navigation afin de les mettre à jour. Vous spécifiez un gestionnaire pour l’événement DropDownList du Init contrôle afin de pouvoir stocker une référence au contrôle à utiliser par le code qui met à jour la DepartmentID clé étrangère.

Dans CoursesAdd.aspx.cs juste après la déclaration de classe partielle, ajoutez un champ de classe pour contenir une référence au DepartmentsDropDownList contrôle :

private DropDownList departmentDropDownList;

Ajoutez un gestionnaire pour l’événement DepartmentsDropDownList du Init contrôle afin de pouvoir stocker une référence au contrôle. Cela vous permet d’obtenir la valeur que l’utilisateur a entrée et de l’utiliser pour mettre à jour la DepartmentID valeur de l’entité Course .

protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
    departmentDropDownList = sender as DropDownList;
}

Ajoutez un gestionnaire pour l’événement DetailsView du Inserting contrôle :

protected void CoursesDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    var departmentID = Convert.ToInt32(departmentDropDownList.SelectedValue);
    e.Values["DepartmentID"] = departmentID;
}

Lorsque l’utilisateur clique sur Insert, l’événement Inserting est déclenché avant l’insertion du nouvel enregistrement. Le code dans le gestionnaire obtient le DepartmentID du DropDownList contrôle et l’utilise pour définir la valeur qui sera utilisée pour la DepartmentID propriété de l’entité Course .

Entity Framework se charge d’ajouter ce cours à la Courses propriété de navigation de l’entité associée Department . Il ajoute également le service à la Department propriété de navigation de l’entité Course .

Exécutez la page.

Capture d’écran de la fenêtre Internet Explorer, qui montre la vue Ajouter des cours avec les champs de texte ID, Titre et Crédits, ainsi qu’une liste déroulante Département.

Entrez un ID, un titre, un nombre de crédits, puis sélectionnez un service, puis cliquez sur Insérer.

Exécutez la page Courses.aspx , puis sélectionnez le même service pour voir le nouveau cours.

Image03

Utilisation des relations plusieurs-à-plusieurs

La relation entre l’ensemble Courses d’entités et l’ensemble People d’entités est une relation plusieurs-à-plusieurs. Une Course entité a une propriété de navigation nommée People qui peut contenir zéro, une ou plusieurs entités associées Person (représentant les instructeurs affectés à l’enseignement de ce cours). Et une Person entité a une propriété de navigation nommée Courses qui peut contenir zéro, une ou plusieurs entités associées Course (représentant les cours que l’instructeur est affecté à enseigner). Un instructeur peut enseigner plusieurs cours, et un cours peut être enseigné par plusieurs instructeurs. Dans cette section de la procédure pas à pas, vous allez ajouter et supprimer les relations entre Person les entités et Course en mettant à jour les propriétés de navigation des entités associées.

Créez une page web nommée InstructorsCourses.aspx qui utilise la page Site.Master master et ajoutez le balisage suivant au Content contrôle nommé Content2:

<h2>Assign Instructors to Courses or Remove from Courses</h2>
    <br />
    <asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" 
        EntitySetName="People"
        Where="it.HireDate is not null" Select="it.LastName + ', ' + it.FirstMidName AS Name, it.PersonID">
    </asp:EntityDataSource>
    Select an Instructor:
    <asp:DropDownList ID="InstructorsDropDownList" runat="server" DataSourceID="InstructorsEntityDataSource"
        AutoPostBack="true" DataTextField="Name" DataValueField="PersonID"
        OnSelectedIndexChanged="InstructorsDropDownList_SelectedIndexChanged" 
        OnDataBound="InstructorsDropDownList_DataBound">
    </asp:DropDownList>
    <h3>
        Assign a Course</h3>
    <br />
    Select a Course:
    <asp:DropDownList ID="UnassignedCoursesDropDownList" runat="server"
        DataTextField="Title" DataValueField="CourseID">
    </asp:DropDownList>
    <br />
    <asp:Button ID="AssignCourseButton" runat="server" Text="Assign" OnClick="AssignCourseButton_Click" />
    <br />
    <asp:Label ID="CourseAssignedLabel" runat="server" Visible="false" Text="Assignment successful"></asp:Label>
    <br />
    <h3>
        Remove a Course</h3>
    <br />
    Select a Course:
    <asp:DropDownList ID="AssignedCoursesDropDownList" runat="server"
        DataTextField="title" DataValueField="courseiD">
    </asp:DropDownList>
    <br />
    <asp:Button ID="RemoveCourseButton" runat="server" Text="Remove" OnClick="RemoveCourseButton_Click" />
    <br />
    <asp:Label ID="CourseRemovedLabel" runat="server" Visible="false" Text="Removal successful"></asp:Label>

Ce balisage crée un EntityDataSource contrôle qui récupère le nom et PersonID les entités des Person instructeurs. Un DropDrownList contrôle est lié au EntityDataSource contrôle. Le DropDownList contrôle spécifie un gestionnaire pour l’événement DataBound . Vous allez utiliser ce gestionnaire pour lier les deux listes déroulantes qui affichent des cours.

Le balisage crée également le groupe de contrôles suivant à utiliser pour attribuer un cours à l’instructeur sélectionné :

  • Contrôle DropDownList permettant de sélectionner un cours à attribuer. Ce contrôle sera rempli avec des cours qui ne sont actuellement pas attribués à l’instructeur sélectionné.
  • Contrôle Button permettant de lancer l’affectation.
  • Contrôle Label permettant d’afficher un message d’erreur si l’affectation échoue.

Enfin, le balisage crée également un groupe de contrôles à utiliser pour supprimer un cours de l’instructeur sélectionné.

Dans InstructorsCourses.aspx.cs, ajoutez une instruction using :

using ContosoUniversity.DAL;

Ajoutez une méthode pour remplir les deux listes déroulantes qui affichent les cours :

private void PopulateDropDownLists()
{
    using (var context = new SchoolEntities())
    {
        var allCourses = (from c in context.Courses
                          select c).ToList();

        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People.Include("Courses")
                          where p.PersonID == instructorID
                          select p).First();

        var assignedCourses = instructor.Courses.ToList();
        var unassignedCourses = allCourses.Except(assignedCourses.AsEnumerable()).ToList();

        UnassignedCoursesDropDownList.DataSource = unassignedCourses;
        UnassignedCoursesDropDownList.DataBind();
        UnassignedCoursesDropDownList.Visible = true;

        AssignedCoursesDropDownList.DataSource = assignedCourses;
        AssignedCoursesDropDownList.DataBind();
        AssignedCoursesDropDownList.Visible = true;
    }
}

Ce code obtient tous les cours du jeu d’entités Courses et les obtient à partir de la Courses propriété de navigation de l’entité Person pour l’instructeur sélectionné. Il détermine ensuite quels cours sont attribués à cet instructeur et remplit les listes déroulantes en conséquence.

Ajoutez un gestionnaire pour l’événement Assign du Click bouton :

protected void AssignCourseButton_Click(object sender, EventArgs e)
{
    using (var context = new SchoolEntities())
    {
        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People
                          where p.PersonID == instructorID
                          select p).First();
        var courseID = Convert.ToInt32(UnassignedCoursesDropDownList.SelectedValue);
        var course = (from c in context.Courses
                      where c.CourseID == courseID
                      select c).First();
        instructor.Courses.Add(course);
        try
        {
            context.SaveChanges();
            PopulateDropDownLists();
            CourseAssignedLabel.Text = "Assignment successful.";
        }
        catch (Exception)
        {
            CourseAssignedLabel.Text = "Assignment unsuccessful.";
            //Add code to log the error.
        }
        CourseAssignedLabel.Visible = true;
    }
}

Ce code obtient l’entité Person de l’instructeur sélectionné, obtient l’entité Course pour le cours sélectionné et ajoute le cours sélectionné à la Courses propriété de navigation de l’entité de Person l’instructeur. Il enregistre ensuite les modifications apportées à la base de données et remplit à nouveau les listes déroulantes afin que les résultats puissent être affichés immédiatement.

Ajoutez un gestionnaire pour l’événement Remove du Click bouton :

protected void RemoveCourseButton_Click(object sender, EventArgs e)
{
    using (var context = new SchoolEntities())
    {
        var instructorID = Convert.ToInt32(InstructorsDropDownList.SelectedValue);
        var instructor = (from p in context.People
                          where p.PersonID == instructorID
                          select p).First();
        var courseID = Convert.ToInt32(AssignedCoursesDropDownList.SelectedValue);
        var courses = instructor.Courses;
        var courseToRemove = new Course();
        foreach (Course c in courses)
        {
            if (c.CourseID == courseID)
            {
                courseToRemove = c;
                break;
            }
        }
        try
        {
            courses.Remove(courseToRemove);
            context.SaveChanges();
            PopulateDropDownLists();
            CourseRemovedLabel.Text = "Removal successful.";
        }
        catch (Exception)
        {
            CourseRemovedLabel.Text = "Removal unsuccessful.";
            //Add code to log the error.
        }
        CourseRemovedLabel.Visible = true;
    }
}

Ce code obtient l’entité Person pour l’instructeur sélectionné, obtient l’entité Course pour le cours sélectionné et supprime le cours sélectionné de la propriété de navigation de Courses l’entitéPerson. Il enregistre ensuite les modifications apportées à la base de données et remplit à nouveau les listes déroulantes afin que les résultats puissent être affichés immédiatement.

Ajoutez du code à la Page_Load méthode qui garantit que les messages d’erreur ne sont pas visibles en l’absence d’erreur à signaler, et ajoutez des gestionnaires pour les DataBound événements et SelectedIndexChanged de la liste déroulante des instructeurs pour remplir les listes déroulantes des cours :

protected void Page_Load(object sender, EventArgs e)
{
    CourseAssignedLabel.Visible = false;
    CourseRemovedLabel.Visible = false;
}

protected void InstructorsDropDownList_DataBound(object sender, EventArgs e)
{
    PopulateDropDownLists();
}

protected void InstructorsDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
    PopulateDropDownLists();
}

Exécutez la page.

Capture d’écran de la fenêtre Internet Explorer, qui montre la vue Affecter des instructeurs aux cours ou Supprimer des cours avec les listes déroulantes correspondantes.

Sélectionnez un instructeur. La liste déroulante Attribuer un cours affiche les cours que l’instructeur n’enseigne pas, et la liste déroulante Supprimer un cours affiche les cours auxquels l’instructeur est déjà affecté. Dans la section Affecter un cours , sélectionnez un cours, puis cliquez sur Affecter. Le cours passe à la liste déroulante Supprimer un cours . Sélectionnez un cours dans la section Supprimer un cours , puis cliquez sur Supprimer. Le cours passe à la liste déroulante Affecter un cours .

Vous avez maintenant vu d’autres façons d’utiliser des données associées. Dans le tutoriel suivant, vous allez apprendre à utiliser l’héritage dans le modèle de données pour améliorer la facilité de maintenance de votre application.