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
Utilisation des données associées, suite
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.
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.
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, Bind
car 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.
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.
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.
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.