Introduzione con Entity Framework 4.0 Database First e ASP.NET 4 Web Forms - Parte 5
di Tom Dykstra
L'applicazione Web di esempio Contoso University illustra come creare applicazioni Web Forms ASP.NET usando Entity Framework 4.0 e Visual Studio 2010. Per informazioni sulla serie di esercitazioni, vedere la prima esercitazione della serie
Utilizzo dei dati correlati, continua
Nell'esercitazione precedente è stato iniziato a usare il EntityDataSource
controllo per lavorare con i dati correlati. Sono stati visualizzati più livelli di gerarchia e dati modificati nelle proprietà di navigazione. In questa esercitazione si continuerà a usare i dati correlati aggiungendo ed eliminando relazioni e aggiungendo una nuova entità con una relazione con un'entità esistente.
Verrà creata una pagina che aggiunge corsi assegnati ai reparti. I reparti esistono già e quando si crea un nuovo corso, contemporaneamente si stabilirà una relazione tra di esso e un reparto esistente.
Si creerà anche una pagina che funziona con una relazione molti-a-molti assegnando un insegnante a un corso (aggiungendo una relazione tra due entità selezionate) o rimuovendo un insegnante da un corso (rimuovendo una relazione tra due entità selezionate). Nel database, l'aggiunta di una relazione tra un insegnante e un corso comporta l'aggiunta CourseInstructor
di una nuova riga alla tabella di associazione. La rimozione di una relazione comporta l'eliminazione di una riga dalla tabella di CourseInstructor
associazione. Tuttavia, questa operazione viene eseguita in Entity Framework impostando le proprietà di navigazione, senza fare riferimento alla CourseInstructor
tabella in modo esplicito.
Aggiunta di un'entità con una relazione a un'entità esistente
Creare una nuova pagina Web denominata CoursesAdd.aspx che usa la pagina master Site.Master e aggiungere il markup seguente al Content
controllo denominato 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>
Questo markup crea un EntityDataSource
controllo che seleziona i corsi, che consente l'inserimento e che specifica un gestore per l'evento Inserting
. Si userà il gestore per aggiornare la Department
proprietà di navigazione quando viene creata una nuova Course
entità.
Il markup crea anche un DetailsView
controllo da usare per l'aggiunta di nuove Course
entità. Il markup usa campi associati per Course
le proprietà dell'entità. È necessario immettere il CourseID
valore perché non si tratta di un campo ID generato dal sistema. È invece un numero di corso che deve essere specificato manualmente al momento della creazione del corso.
Utilizzare un campo modello per la Department
proprietà di navigazione perché le proprietà di navigazione non possono essere utilizzate con BoundField
i controlli. Il campo modello fornisce un elenco a discesa per selezionare il reparto. L'elenco a discesa è associato al Departments
set di entità utilizzando Eval
anziché Bind
, anche in questo caso perché non è possibile associare direttamente le proprietà di navigazione per aggiornarle. Specificare un gestore per l'evento DropDownList
del Init
controllo in modo che sia possibile archiviare un riferimento al controllo da utilizzare dal codice che aggiorna la DepartmentID
chiave esterna.
In CoursesAdd.aspx.cs subito dopo la dichiarazione di classe parziale aggiungere un campo classe per contenere un riferimento al DepartmentsDropDownList
controllo:
private DropDownList departmentDropDownList;
Aggiungere un gestore per l'evento DepartmentsDropDownList
del Init
controllo in modo che sia possibile archiviare un riferimento al controllo. In questo modo è possibile ottenere il valore immesso dall'utente e usarlo per aggiornare il DepartmentID
valore dell'entità Course
.
protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
departmentDropDownList = sender as DropDownList;
}
Aggiungere un gestore per l'evento DetailsView
del Inserting
controllo:
protected void CoursesDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
var departmentID = Convert.ToInt32(departmentDropDownList.SelectedValue);
e.Values["DepartmentID"] = departmentID;
}
Quando l'utente fa clic su Insert
, l'evento viene generato prima dell'inserimento Inserting
del nuovo record. Il codice nel gestore ottiene l'oggetto DepartmentID
dal DropDownList
controllo e lo usa per impostare il valore che verrà usato per la DepartmentID
proprietà dell'entità Course
.
Entity Framework si occuperà dell'aggiunta di questo corso alla Courses
proprietà di navigazione dell'entità associata Department
. Aggiunge anche il reparto alla Department
proprietà di navigazione dell'entità Course
.
Eseguire la pagina.
Immettere un ID, un titolo, un numero di crediti e selezionare un reparto, quindi fare clic su Inserisci.
Eseguire la pagina Courses.aspx e selezionare lo stesso reparto per visualizzare il nuovo corso.
Utilizzo delle relazioni molti-a-molti
La relazione tra il Courses
set di entità e il People
set di entità è una relazione molti-a-molti. Un'entità Course
ha una proprietà di navigazione denominata People
che può contenere zero, una o più entità correlate Person
(che rappresentano gli insegnanti assegnati per insegnare tale corso). Person
Un'entità ha una proprietà di navigazione denominata Courses
che può contenere zero, una o più entità correlate Course
(che rappresenta i corsi assegnati all'insegnante per l'insegnamento). Un insegnante potrebbe insegnare più corsi e un corso potrebbe essere insegnato da più insegnanti. In questa sezione della procedura dettagliata verranno aggiunte e rimosse le relazioni tra Person
le entità e Course
aggiornando le proprietà di navigazione delle entità correlate.
Creare una nuova pagina Web denominata InstructorsCourses.aspx che usa la pagina master Site.Master e aggiungere il markup seguente al Content
controllo denominato 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>
Questo markup crea un EntityDataSource
controllo che recupera il nome e PersonID
le Person
entità per gli istruttori. Un DropDrownList
controllo è associato al EntityDataSource
controllo . Il DropDownList
controllo specifica un gestore per l'evento DataBound
. Questo gestore verrà usato per associare i due elenchi a discesa che visualizzano i corsi.
Il markup crea anche il gruppo di controlli seguente da usare per assegnare un corso all'insegnante selezionato:
- Controllo
DropDownList
per la selezione di un corso da assegnare. Questo controllo verrà popolato con corsi attualmente non assegnati all'insegnante selezionato. - Controllo
Button
per avviare l'assegnazione. - Controllo
Label
per visualizzare un messaggio di errore se l'assegnazione non riesce.
Infine, il markup crea anche un gruppo di controlli da usare per rimuovere un corso dall'insegnante selezionato.
In InstructorsCourses.aspx.cs aggiungere un'istruzione using:
using ContosoUniversity.DAL;
Aggiungere un metodo per popolare i due elenchi a discesa che visualizzano i corsi:
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;
}
}
Questo codice ottiene tutti i corsi dal Courses
set di entità e ottiene i corsi dalla Courses
proprietà di navigazione dell'entità per l'insegnante Person
selezionato. Determina quindi i corsi assegnati a tale insegnante e popola gli elenchi a discesa di conseguenza.
Aggiungere un gestore per l'evento Assign
del Click
pulsante:
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;
}
}
Questo codice ottiene l'entità Person
per l'insegnante selezionato, ottiene l'entità Course
per il corso selezionato e aggiunge il corso selezionato alla Courses
proprietà di navigazione dell'entità dell'insegnante Person
. Salva quindi le modifiche al database e ripopola gli elenchi a discesa in modo che i risultati possano essere visualizzati immediatamente.
Aggiungere un gestore per l'evento Remove
del Click
pulsante:
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;
}
}
Questo codice ottiene l'entità Person
per l'insegnante selezionato, ottiene l'entità Course
per il corso selezionato e rimuove il corso selezionato dalla Person
proprietà di navigazione dell'entità Courses
. Salva quindi le modifiche al database e ripopola gli elenchi a discesa in modo che i risultati possano essere visualizzati immediatamente.
Aggiungere codice al Page_Load
metodo che assicura che i messaggi di errore non siano visibili quando non è presente alcun errore da segnalare e aggiungere gestori per gli DataBound
eventi e SelectedIndexChanged
dell'elenco a discesa degli insegnanti per popolare gli elenchi a discesa dei corsi:
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();
}
Eseguire la pagina.
Selezionare un insegnante. L'elenco a discesa Assegna un corso visualizza i corsi a cui l'insegnante non insegna e nell'elenco a discesa Rimuovi un corso vengono visualizzati i corsi a cui l'insegnante è già assegnato. Nella sezione Assegna un corso selezionare un corso e quindi fare clic su Assegna. Il corso passa all'elenco a discesa Rimuovi un corso . Selezionare un corso nella sezione Rimuovi un corso e fare clic su Rimuovi. Il corso passa all'elenco a discesa Assegna un corso .
Sono stati ora illustrati altri modi per lavorare con i dati correlati. Nell'esercitazione seguente si apprenderà come usare l'ereditarietà nel modello di dati per migliorare la gestibilità dell'applicazione.