Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
par Tom Dykstra
L’exemple d’application web Contoso University montre comment créer ASP.NET applications 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 didacticiel de la série
Utilisation des données associées
Dans le tutoriel précédent, vous avez utilisé le EntityDataSource contrôle pour filtrer, trier et regrouper des données. Dans ce tutoriel, vous allez afficher et mettre à jour les données associées.
Vous allez créer la page Instructeurs qui affiche une liste d’instructeurs. Lorsque vous sélectionnez un instructeur, vous voyez une liste de cours enseignés par ce formateur. Lorsque vous sélectionnez un cours, vous voyez des détails pour le cours et une liste d’étudiants inscrits dans le cours. Vous pouvez modifier le nom de l’instructeur, la date d’embauche et l’affectation de bureau. L’attribution d’office est un ensemble d’entités distinct auquel vous accédez via une propriété de navigation.
Vous pouvez lier des données de référence aux données de détail dans le balisage ou dans le code. Dans cette partie du tutoriel, vous allez utiliser les deux méthodes.
Affichage et mise à jour des entités associées dans un contrôle GridView
Créez une page web nommée Instructors.aspx qui utilise la page maître Site.Master et ajoutez le balisage suivant au Content contrôle nommé Content2:
<h2>Instructors</h2>
<div>
<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People"
Where="it.HireDate is not null" Include="OfficeAssignment" EnableUpdate="True">
</asp:EntityDataSource>
</div>
Ce balisage crée un EntityDataSource contrôle qui sélectionne les instructeurs et active les mises à jour. L’élément div configure le balisage pour qu’il s’affiche à gauche afin que vous puissiez ajouter une colonne à droite ultérieurement.
Entre le EntityDataSource balisage et la balise de fermeture </div> , ajoutez le balisage suivant qui crée un GridView contrôle et un Label contrôle que vous utiliserez pour les messages d’erreur :
<asp:GridView ID="InstructorsGridView" runat="server" AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" DataKeyNames="PersonID" DataSourceID="InstructorsEntityDataSource"
OnSelectedIndexChanged="InstructorsGridView_SelectedIndexChanged"
SelectedRowStyle-BackColor="LightGray"
onrowupdating="InstructorsGridView_RowUpdating">
<Columns>
<asp:CommandField ShowSelectButton="True" ShowEditButton="True" />
<asp:TemplateField HeaderText="Name" SortExpression="LastName">
<ItemTemplate>
<asp:Label ID="InstructorLastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
<asp:Label ID="InstructorFirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="InstructorLastNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>' Width="7em"></asp:TextBox>
<asp:TextBox ID="InstructorFirstNameTextBox" runat="server" Text='<%# Bind("LastName") %>' Width="7em"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Hire Date" SortExpression="HireDate">
<ItemTemplate>
<asp:Label ID="InstructorHireDateLabel" runat="server" Text='<%# Eval("HireDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="InstructorHireDateTextBox" runat="server" Text='<%# Bind("HireDate", "{0:d}") %>' Width="7em"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Office Assignment" SortExpression="OfficeAssignment.Location">
<ItemTemplate>
<asp:Label ID="InstructorOfficeLabel" runat="server" Text='<%# Eval("OfficeAssignment.Location") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="InstructorOfficeTextBox" runat="server"
Text='<%# Eval("OfficeAssignment.Location") %>' Width="7em"
oninit="InstructorOfficeTextBox_Init"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
<SelectedRowStyle BackColor="LightGray"></SelectedRowStyle>
</asp:GridView>
<asp:Label ID="ErrorMessageLabel" runat="server" Text="" Visible="false" ViewStateMode="Disabled"></asp:Label>
Ce GridView contrôle active la sélection de lignes, met en surbrillance la ligne sélectionnée avec une couleur d’arrière-plan gris clair et spécifie les gestionnaires pour les événements SelectedIndexChanged et Updating (que vous allez créer ultérieurement). Il spécifie PersonID également pour la DataKeyNames propriété, afin que la valeur de clé de la ligne sélectionnée puisse être passée à un autre contrôle que vous ajouterez ultérieurement.
La dernière colonne contient l’affectation du bureau de l’enseignant, qui est stockée dans une propriété de navigation de l’entité Person, car elle provient d’une entité associée. Notez que l’élément EditItemTemplate spécifie Eval au lieu de Bind, car le contrôle GridView ne peut pas se lier directement aux propriétés de navigation pour les mettre à jour. Vous allez mettre à jour l’affectation du bureau dans le code. Pour ce faire, vous aurez besoin d'une référence au contrôle TextBox, et vous l'obtiendrez et l'enregistrerez dans l'événement Init du contrôle TextBox.
GridView Le contrôle suivant est un Label contrôle utilisé pour les messages d’erreur. La propriété du contrôle est Visible, et l’état d’affichage false est désactivé, de sorte que l’étiquette s’affiche uniquement lorsque le code le rend visible en réponse à une erreur.
Ouvrez le fichier Instructors.aspx.cs et ajoutez l’instruction suivante using :
using ContosoUniversity.DAL;
Ajoutez un champ de classe privée immédiatement après la déclaration du nom de classe partiel pour contenir une référence à la zone de texte d'attribution de bureau.
private TextBox instructorOfficeTextBox;
Ajoutez une ébauche pour le SelectedIndexChanged gestionnaire d’événements auquel vous ajouterez du code ultérieurement. Ajoutez également un gestionnaire pour l’événement du contrôle d’affectation TextBox de bureau afin de pouvoir stocker une référence au Init contrôle.TextBox Vous utiliserez cette référence pour obtenir la valeur entrée par l’utilisateur afin de mettre à jour l’entité associée à la propriété de navigation.
protected void InstructorsGridView_SelectedIndexChanged(object sender, EventArgs e)
{
}
protected void InstructorOfficeTextBox_Init(object sender, EventArgs e)
{
instructorOfficeTextBox = sender as TextBox;
}
Vous allez utiliser l’événement GridView du Updating contrôle pour mettre à jour la Location propriété de l’entité associée OfficeAssignment . Ajoutez le gestionnaire suivant pour l’événement Updating :
protected void InstructorsGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
using (var context = new SchoolEntities())
{
var instructorBeingUpdated = Convert.ToInt32(e.Keys[0]);
var officeAssignment = (from o in context.OfficeAssignments
where o.InstructorID == instructorBeingUpdated
select o).FirstOrDefault();
try
{
if (String.IsNullOrWhiteSpace(instructorOfficeTextBox.Text) == false)
{
if (officeAssignment == null)
{
context.OfficeAssignments.AddObject(OfficeAssignment.CreateOfficeAssignment(instructorBeingUpdated, instructorOfficeTextBox.Text, null));
}
else
{
officeAssignment.Location = instructorOfficeTextBox.Text;
}
}
else
{
if (officeAssignment != null)
{
context.DeleteObject(officeAssignment);
}
}
context.SaveChanges();
}
catch (Exception)
{
e.Cancel = true;
ErrorMessageLabel.Visible = true;
ErrorMessageLabel.Text = "Update failed.";
//Add code to log the error.
}
}
}
Ce code est exécuté lorsque l’utilisateur clique sur Mettre à jour dans une GridView ligne. Le code utilise LINQ to Entities pour récupérer l’entité OfficeAssignment associée à l’entité actuelle Person , à l’aide de la PersonID ligne sélectionnée à partir de l’argument d’événement.
Le code effectue ensuite l’une des actions suivantes en fonction de la valeur du InstructorOfficeTextBox contrôle :
- Si la zone de texte a une valeur et qu’aucune entité n’est
OfficeAssignmentà mettre à jour, elle en crée une. - Si la zone de texte a une valeur et qu’il existe une
OfficeAssignmententité, elle met à jour la valeur deLocationpropriété. - Si la zone de texte est vide et qu’une
OfficeAssignmententité existe, elle supprime l’entité.
Après cela, il enregistre les modifications apportées à la base de données. Si une exception se produit, elle affiche un message d’erreur.
Exécutez la page Web.
Cliquez sur Modifier et tous les champs sont modifiés en zones de texte.
Modifiez l’une de ces valeurs, y compris l’affectation d’Office. Cliquez sur Mettre à jour et vous verrez les modifications reflétées dans la liste.
Affichage d’entités associées dans un contrôle distinct
Chaque instructeur peut enseigner un ou plusieurs cours. Vous allez donc ajouter un EntityDataSource contrôle et un GridView contrôle pour répertorier les cours associés à l’instructeur sélectionné dans le contrôle des instructeurs GridView . Pour créer un titre et ajouter le contrôle EntityDataSource pour les entités de cours, insérez le balisage suivant entre le contrôle d'erreur de message Label et la balise de fermeture </div> :
<h3>Courses Taught</h3>
<asp:EntityDataSource ID="CoursesEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="Courses"
Where="@PersonID IN (SELECT VALUE instructor.PersonID FROM it.People AS instructor)">
<WhereParameters>
<asp:ControlParameter ControlID="InstructorsGridView" Type="Int32" Name="PersonID" PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
Le paramètre Where contient la valeur du PersonID du formateur dont la ligne est sélectionnée dans l'élément de contrôle InstructorsGridView. La Where propriété contient une commande de sous-sélection qui obtient toutes les entités associées Person à partir de la propriété de Course navigation d’une People entité et sélectionne l’entité Course uniquement si l’une des entités associées Person contient la valeur sélectionnéePersonID.
Pour créer le GridView contrôle, ajoutez le marquage suivant immédiatement après le CoursesEntityDataSource contrôle (avant la balise fermante </div>) :
<asp:GridView ID="CoursesGridView" runat="server"
DataSourceID="CoursesEntityDataSource"
AllowSorting="True" AutoGenerateColumns="False"
SelectedRowStyle-BackColor="LightGray"
DataKeyNames="CourseID">
<EmptyDataTemplate>
<p>No courses found.</p>
</EmptyDataTemplate>
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="CourseID" HeaderText="ID" ReadOnly="True" SortExpression="CourseID" />
<asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
<asp:TemplateField HeaderText="Department" SortExpression="DepartmentID">
<ItemTemplate>
<asp:Label ID="GridViewDepartmentLabel" runat="server" Text='<%# Eval("Department.Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Étant donné qu’aucun cours ne s’affiche si aucun instructeur n’est sélectionné, un EmptyDataTemplate élément est inclus.
Exécutez la page Web.
Sélectionnez un instructeur qui a un ou plusieurs cours attribués, et le cours ou les cours apparaissent dans la liste. (Remarque : bien que le schéma de base de données autorise plusieurs cours, dans les données de test fournies avec la base de données, aucun instructeur n’a réellement plusieurs cours. Vous pouvez ajouter des cours à la base de données vous-même à l’aide de la fenêtre explorateur de serveurs ou de la page CoursesAdd.aspx , que vous ajouterez dans un didacticiel ultérieur.)
L'élément de contrôle CoursesGridView affiche uniquement quelques champs du cours. Pour afficher tous les détails d’un cours, vous utiliserez un DetailsView contrôle pour le cours que l’utilisateur sélectionne. Dans Instructors.aspx, ajoutez le balisage suivant après la balise de fermeture </div> (veillez à placer ce balisage après la balise div fermante, pas avant) :
<div>
<h3>Course Details</h3>
<asp:EntityDataSource ID="CourseDetailsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="Courses"
AutoGenerateWhereClause="False" Where="it.CourseID = @CourseID" Include="Department,OnlineCourse,OnsiteCourse,StudentGrades.Person"
OnSelected="CourseDetailsEntityDataSource_Selected">
<WhereParameters>
<asp:ControlParameter ControlID="CoursesGridView" Type="Int32" Name="CourseID" PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
<asp:DetailsView ID="CourseDetailsView" runat="server" AutoGenerateRows="False"
DataSourceID="CourseDetailsEntityDataSource">
<EmptyDataTemplate>
<p>
No course selected.</p>
</EmptyDataTemplate>
<Fields>
<asp:BoundField DataField="CourseID" HeaderText="ID" ReadOnly="True" SortExpression="CourseID" />
<asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
<asp:BoundField DataField="Credits" HeaderText="Credits" SortExpression="Credits" />
<asp:TemplateField HeaderText="Department">
<ItemTemplate>
<asp:Label ID="DetailsViewDepartmentLabel" runat="server" Text='<%# Eval("Department.Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Location">
<ItemTemplate>
<asp:Label ID="LocationLabel" runat="server" Text='<%# Eval("OnsiteCourse.Location") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="URL">
<ItemTemplate>
<asp:Label ID="URLLabel" runat="server" Text='<%# Eval("OnlineCourse.URL") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
</div>
Ce balisage crée un EntityDataSource contrôle lié au Courses jeu d’entités. La propriété Where sélectionne un cours en utilisant la valeur CourseID de la ligne sélectionnée dans le contrôle des cours GridView. Le balisage spécifie un gestionnaire pour l’événement Selected , que vous utiliserez ultérieurement pour afficher les notes des étudiants, qui est un autre niveau inférieur dans la hiérarchie.
Dans Instructors.aspx.cs, créez le stub suivant pour la CourseDetailsEntityDataSource_Selected méthode. (Vous allez remplir ce stub plus loin dans le tutoriel ; pour l’instant, vous en avez besoin pour que la page compile et s’exécute.)
protected void CourseDetailsEntityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
}
Exécutez la page Web.
Initialement, il n’y a pas de détails de cours, car aucun cours n’est sélectionné. Sélectionnez un instructeur auquel un cours est attribué, puis sélectionnez un cours pour afficher les détails.
Utilisation de l’événement EntityDataSource « Selected » pour afficher les données associées
Enfin, vous souhaitez afficher tous les étudiants inscrits et leurs notes pour le cours sélectionné. Pour ce faire, vous allez utiliser l’événement Selected du EntityDataSource contrôle lié au cours DetailsView.
Dans Instructors.aspx, ajoutez le balisage suivant après le DetailsView contrôle :
<h3>Student Grades</h3>
<asp:ListView ID="GradesListView" runat="server">
<EmptyDataTemplate>
<p>No student grades found.</p>
</EmptyDataTemplate>
<LayoutTemplate>
<table border="1" runat="server" id="itemPlaceholderContainer">
<tr runat="server">
<th runat="server">
Name
</th>
<th runat="server">
Grade
</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="StudentLastNameLabel" runat="server" Text='<%# Eval("Person.LastName") %>' />,
<asp:Label ID="StudentFirstNameLabel" runat="server" Text='<%# Eval("Person.FirstMidName") %>' />
</td>
<td>
<asp:Label ID="StudentGradeLabel" runat="server" Text='<%# Eval("Grade") %>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Ce balisage crée un ListView contrôle qui affiche une liste d’étudiants et leurs notes pour le cours sélectionné. Aucune source de données n’est spécifiée, car vous allez lier le contrôle aux données dans le code. L’élément EmptyDataTemplate fournit un message à afficher lorsqu’aucun cours n’est sélectionné, dans ce cas, il n’y a pas d’étudiants à afficher. L’élément LayoutTemplate crée une table HTML pour afficher la liste et ItemTemplate spécifie les colonnes à afficher. L’ID d’étudiant et la note de l’étudiant proviennent de l’entité StudentGrade , et le nom de l’étudiant provient de l’entité Person que Entity Framework met à disposition dans la Person propriété de navigation de l’entité StudentGrade .
Dans Instructors.aspx.cs, remplacez la méthode stubbed-out CourseDetailsEntityDataSource_Selected par le code suivant :
protected void CourseDetailsEntityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
var course = e.Results.Cast<Course>().FirstOrDefault();
if (course != null)
{
var studentGrades = course.StudentGrades.ToList();
GradesListView.DataSource = studentGrades;
GradesListView.DataBind();
}
}
L’argument d’événement de cet événement fournit les données sélectionnées sous la forme d’une collection, ce qui aura zéro élément si rien n’est sélectionné ou un élément si une Course entité est sélectionnée. Si une Course entité est sélectionnée, le code utilise la First méthode pour convertir la collection en un seul objet. Il obtient ensuite des entités StudentGrade à partir de la propriété de navigation, les convertit en une collection, puis lie le composant GradesListView à cette collection.
Cela suffit pour afficher les notes, mais vous souhaitez vous assurer que le message dans le modèle de données vide s’affiche la première fois que la page est affichée et chaque fois qu’un cours n’est pas sélectionné. Pour ce faire, créez la méthode suivante, que vous allez appeler à partir de deux emplacements :
private void ClearStudentGradesDataSource()
{
var emptyStudentGradesList = new List<StudentGrade>();
GradesListView.DataSource = emptyStudentGradesList;
GradesListView.DataBind();
}
Appelez cette nouvelle méthode à partir de la Page_Load méthode pour afficher le modèle de données vide la première fois que la page est affichée. Et appelez-le à partir de la méthode InstructorsGridView_SelectedIndexChanged, car cet événement est déclenché lorsqu’un instructeur est sélectionné, ce qui signifie que les nouveaux cours sont chargés dans le contrôle GridView des cours et qu’aucun n’est encore sélectionné. Voici les deux appels :
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ClearStudentGradesDataSource();
}
}
protected void InstructorsGridView_SelectedIndexChanged(object sender, EventArgs e)
{
ClearStudentGradesDataSource();
}
Exécutez la page Web.
Sélectionnez un instructeur auquel un cours est attribué, puis sélectionnez le cours.
Vous avez maintenant vu quelques façons d’utiliser les données associées. Dans le tutoriel suivant, vous allez apprendre à ajouter des relations entre des entités existantes, à supprimer des relations et à ajouter une nouvelle entité qui a une relation à une entité existante.