Introduzione con Entity Framework 4.0 Database First e ASP.NET 4 Web Forms - Parte 2

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

Controllo EntityDataSource

Nell'esercitazione precedente è stato creato un sito Web, un database e un modello di dati. In questa esercitazione si usa il EntityDataSource controllo fornito da ASP.NET per semplificare l'uso di un modello di dati di Entity Framework. Si creerà un GridView controllo per la visualizzazione e la modifica dei dati degli studenti, un DetailsView controllo per l'aggiunta di nuovi studenti e un DropDownList controllo per la selezione di un reparto (che verrà usato più avanti per la visualizzazione dei corsi associati).

Screenshot della finestra di Internet Explorer, che mostra la visualizzazione Elenco studenti con un elenco di nomi, date di iscrizione e corsi degli studenti.

Screenshot della finestra di Internet Explorer, che mostra la visualizzazione Aggiungi nuovi studenti con il nome e la data di registrazione di John Smith compilati nei campi di testo.

Screenshot della finestra di Internet Explorer, che mostra la visualizzazione Corsi per reparto con un menu a discesa per i reparti.

Si noti che in questa applicazione non si aggiungerà la convalida di input alle pagine che aggiornano il database e alcune delle operazioni di gestione degli errori non saranno affidabili come sarebbe necessario in un'applicazione di produzione. In questo modo l'esercitazione è incentrata su Entity Framework e la impedisce di ottenere troppo tempo. Per informazioni dettagliate su come aggiungere queste funzionalità all'applicazione, vedere Convalida dell'input dell'utente in Pagine Web ASP.NET e gestione degli errori in ASP.NET pagine e applicazioni.

Aggiunta e configurazione del controllo EntityDataSource

Si inizierà configurando un EntityDataSource controllo per leggere Person le entità dal People set di entità.

Assicurarsi di avere aperto Visual Studio e di usare il progetto creato nella parte 1. Se il progetto non è stato compilato dopo aver creato il modello di dati o dopo l'ultima modifica apportata, compilare ora il progetto. Le modifiche apportate al modello di dati non vengono rese disponibili per la finestra di progettazione fino alla compilazione del progetto.

Creare una nuova pagina Web usando il modello Pagina master usando il modello Pagina master e denominarlo Students.aspx.

Immagine23

Specificare Site.Master come pagina master. Tutte le pagine create per queste esercitazioni useranno questa pagina master.

Immagine24

Nella visualizzazione Origine aggiungere un'intestazione h2 al Content controllo denominato Content2, come illustrato nell'esempio seguente:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
   <h2>Student List</h2>
</asp:Content>

Dalla scheda Dati della Casella degli strumenti trascinare un EntityDataSource controllo nella pagina, rilasciarlo sotto l'intestazione e modificare l'ID in StudentsEntityDataSource:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Student List</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server">
    </asp:EntityDataSource>
</asp:Content>

Passare alla visualizzazione Progettazione , fare clic sullo smart tag del controllo origine dati e quindi su Configura origine dati per avviare la procedura guidata Configura origine dati .

Immagine01

Nel passaggio Configura objectContext della procedura guidata selezionare SchoolEntities come valore per Connessione denominata e selezionare SchoolEntities come valore DefaultContainerName . Quindi fare clic su Avanti.

Immagine02

Nota: se a questo punto viene visualizzata la finestra di dialogo seguente, è necessario compilare il progetto prima di procedere.

Immagine25

Nel passaggio Configura selezione dati selezionare Persone come valore per EntitySetName. In Seleziona verificare che la casella di controllo Seleziona A sia selezionata. Selezionare quindi le opzioni per abilitare l'aggiornamento e l'eliminazione. Al termine, fare clic su Fine.

Immagine03

Configurazione delle regole di database per consentire l'eliminazione

Verrà creata una pagina che consente agli utenti di eliminare gli studenti dalla Person tabella, che ha tre relazioni con altre tabelle (Course, StudentGradee OfficeAssignment). Per impostazione predefinita, il database impedisce l'eliminazione di una riga in Person se sono presenti righe correlate in una delle altre tabelle. È possibile eliminare manualmente prima le righe correlate oppure configurare il database per eliminarle automaticamente quando si elimina una Person riga. Per i record degli studenti in questa esercitazione, si configurerà il database per eliminare automaticamente i dati correlati. Poiché gli studenti possono avere righe correlate solo nella StudentGrade tabella, è necessario configurare solo una delle tre relazioni.

Se si usa il file School.mdf scaricato dal progetto che include questa esercitazione, è possibile ignorare questa sezione perché queste modifiche alla configurazione sono già state apportate. Se il database è stato creato eseguendo uno script, configurare il database eseguendo le procedure seguenti.

In Esplora server aprire il diagramma di database creato nella parte 1. Fare clic con il pulsante destro del mouse sulla relazione tra Person e StudentGrade (la linea tra le tabelle) e quindi scegliere Proprietà.

Immagine04

Nella finestra Proprietà espandere INSERT e UPDATE Specification e impostare la proprietà DeleteRule su Cascade.

Immagine05

Salvare e chiudere il diagramma. Se viene chiesto se si vuole aggiornare il database, fare clic su .

Per assicurarsi che il modello mantenga le entità in memoria sincronizzate con le operazioni eseguite dal database, è necessario impostare le regole corrispondenti nel modello di dati. Aprire SchoolModel.edmx, fare clic con il pulsante destro del mouse sulla linea di associazione tra Person e StudentGradee quindi scegliere Proprietà.

Immagine21

Nella finestra Proprietà impostare End1 OnDelete su Cascade.

Immagine22

Salvare e chiudere il file SchoolModel.edmx e quindi ricompilare il progetto.

In generale, quando il database cambia, sono disponibili diverse opzioni per la sincronizzazione del modello:

  • Per determinati tipi di modifiche, ad esempio l'aggiunta o l'aggiornamento di tabelle, viste o stored procedure, fare clic con il pulsante destro del mouse nella finestra di progettazione e selezionare Aggiorna modello dal database per fare in modo che la finestra di progettazione faccia in modo che le modifiche vengano apportate automaticamente.
  • Rigenerare il modello di dati.
  • Apportare aggiornamenti manuali come questo.

In questo caso, è possibile rigenerare il modello o aggiornare le tabelle interessate dalla modifica della relazione, ma è necessario apportare nuovamente la modifica del nome del campo (da FirstName a FirstMidName).

Uso di un controllo GridView per leggere e aggiornare le entità

In questa sezione si userà un GridView controllo per visualizzare, aggiornare o eliminare studenti.

Aprire o passare a Students.aspx e passare alla visualizzazione Struttura . Nella scheda Dati della Casella degli strumenti trascinare un GridView controllo a destra del EntityDataSource controllo, denominarlo StudentsGridView, fare clic sullo smart tag e quindi selezionare StudentsEntityDataSource come origine dati.

Image06

Fare clic su Aggiorna schema (fare clic su se viene richiesto di confermare), quindi fare clic su Abilita paging, Abilita ordinamento, Abilita modifica e Abilita eliminazione.

Fare clic su Modifica colonne.

Image10

Nella casella Campi selezionati eliminare PersonID, LastName e HireDate. In genere non viene visualizzata una chiave di record per gli utenti, la data di assunzione non è rilevante per gli studenti e si inseriscono entrambe le parti del nome in un campo, quindi è necessario solo uno dei campi del nome.

Immagine11

Selezionare il campo FirstMidName e quindi fare clic su Converti questo campo in un campo Modello.

Eseguire la stessa operazione per EnrollmentDate.

Immagine13

Fare clic su OK e quindi passare a Visualizzazione origine . Le modifiche rimanenti saranno più facili da eseguire direttamente nel markup. Il markup del GridView controllo è ora simile all'esempio seguente.

<asp:GridView ID="StudentsGridView" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="PersonID" 
        DataSourceID="StudentsEntityDataSource">
        <Columns>
            <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
            <asp:TemplateField HeaderText="FirstMidName" SortExpression="FirstMidName">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="EnrollmentDate" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

La prima colonna dopo il campo del comando è un campo modello che attualmente visualizza il nome. Modificare il markup per questo campo modello in modo che sia simile all'esempio seguente:

<asp:TemplateField HeaderText="Name" SortExpression="LastName">
                <EditItemTemplate>
                    <asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>'></asp:TextBox>
                    <asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
                    <asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

In modalità di visualizzazione, due Label controlli visualizzano il nome e il cognome. In modalità di modifica, vengono fornite due caselle di testo in modo da poter modificare il nome e il cognome. Come per i Label controlli in modalità di visualizzazione, si usano Bind espressioni ed Eval esattamente come si farebbe con ASP.NET controlli origine dati che si connettono direttamente ai database. L'unica differenza è che si specificano proprietà di entità anziché colonne di database.

L'ultima colonna è un campo modello che visualizza la data di registrazione. Modificare il markup per questo campo in modo che sia simile all'esempio seguente:

<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="EnrollmentDateTextBox" runat="server" Text='<%# Bind("EnrollmentDate", "{0:d}") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="EnrollmentDateLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

Sia in modalità di visualizzazione che di modifica, la stringa di formato "{0,d}" determina la visualizzazione della data nel formato "data breve". Il computer potrebbe essere configurato per visualizzare questo formato in modo diverso rispetto alle immagini visualizzate in questa esercitazione.

Si noti che in ognuno di questi campi modello, la finestra di progettazione usa un'espressione Bind per impostazione predefinita, ma è stata modificata in un'espressione EvalItemTemplate negli elementi . L'espressione Bind rende i dati disponibili nelle GridView proprietà del controllo nel caso in cui sia necessario accedere ai dati nel codice. In questa pagina non è necessario accedere a questi dati nel codice, quindi è possibile usare Eval, che è più efficiente. Per altre informazioni, vedere Recupero dei dati dai controlli dati.

Revisione del markup del controllo EntityDataSource per migliorare le prestazioni

Nel markup per il EntityDataSource controllo rimuovere gli ConnectionString attributi e DefaultContainerName e sostituirli con un ContextTypeName="ContosoUniversity.DAL.SchoolEntities" attributo . Si tratta di una modifica che è necessario apportare ogni volta che si crea un EntityDataSource controllo, a meno che non sia necessario usare una connessione diversa da quella hardcoded nella classe di contesto dell'oggetto. L'uso dell'attributo ContextTypeName offre i vantaggi seguenti:

  • Prestazioni migliori. Quando il EntityDataSource controllo inizializza il modello di dati usando gli ConnectionString attributi e DefaultContainerName , esegue operazioni aggiuntive per caricare i metadati in ogni richiesta. Non è necessario se si specifica l'attributo ContextTypeName .
  • Il caricamento differita è attivato per impostazione predefinita nelle classi di contesto oggetto generate (ad esempio SchoolEntities in questa esercitazione) in Entity Framework 4.0. Ciò significa che le proprietà di navigazione vengono caricate automaticamente con i dati correlati quando necessario. Il caricamento differita viene illustrato in modo più dettagliato più avanti in questa esercitazione.
  • Tutte le personalizzazioni applicate alla classe del contesto dell'oggetto (in questo caso la SchoolEntities classe ) saranno disponibili per i controlli che usano il EntityDataSource controllo . La personalizzazione della classe di contesto dell'oggetto è un argomento avanzato non trattato in questa serie di esercitazioni. Per altre informazioni, vedere Estensione dei tipi generati da Entity Framework.

Il markup sarà ora simile all'esempio seguente (l'ordine delle proprietà potrebbe essere diverso):

<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EntitySetName="People"
        EnableDelete="True" EnableUpdate="True">
    </asp:EntityDataSource>

L'attributo EnableFlattening fa riferimento a una funzionalità necessaria nelle versioni precedenti di Entity Framework perché le colonne chiave esterna non sono state esposte come proprietà di entità. La versione corrente consente di usare associazioni di chiavi esterne, ovvero le proprietà di chiave esterna vengono esposte per tutte le associazioni molti-a-molti. Se le entità hanno proprietà di chiave esterna e nessun tipo complesso, è possibile lasciare questo attributo impostato su False. Non rimuovere l'attributo dal markup, perché il valore predefinito è True. Per altre informazioni, vedere Flattening Objects (EntityDataSource).

Eseguire la pagina e visualizzare un elenco di studenti e dipendenti (si filtra solo per gli studenti nell'esercitazione successiva). Il nome e il cognome vengono visualizzati insieme.

Immagine07

Per ordinare la visualizzazione, fare clic su un nome di colonna.

Fare clic su Modifica in qualsiasi riga. Le caselle di testo vengono visualizzate in cui è possibile modificare il nome e il cognome.

Immagine08

Il pulsante Elimina funziona anche. Fare clic su Elimina per una riga con una data di registrazione e la riga scompare. Le righe senza una data di registrazione rappresentano insegnanti e si potrebbe ottenere un errore di integrità referenziale. Nell'esercitazione successiva si filtra l'elenco in modo da includere solo studenti.

Visualizzazione di dati da una proprietà di navigazione

Si supponga ora di voler conoscere il numero di corsi a cui ogni studente è iscritto. Entity Framework fornisce tali informazioni nella StudentGrades proprietà di navigazione dell'entità Person . Poiché la progettazione del database non consente l'iscrizione di uno studente in un corso senza avere un voto assegnato, per questa esercitazione è possibile presupporre che la presenza di una riga nella riga di StudentGrade tabella associata a un corso sia uguale a quella registrata nel corso. La Courses proprietà di navigazione è solo per gli istruttori.

Quando si usa l'attributo ContextTypeName del EntityDataSource controllo, Entity Framework recupera automaticamente le informazioni per una proprietà di navigazione quando si accede a tale proprietà. Questa operazione è denominata caricamento differita. Tuttavia, ciò può risultare inefficiente, perché comporta una chiamata separata al database ogni volta che sono necessarie informazioni aggiuntive. Se sono necessari dati dalla proprietà di navigazione per ogni entità restituita dal EntityDataSource controllo, è più efficiente recuperare i dati correlati insieme all'entità stessa in una singola chiamata al database. Viene chiamato caricamento eager e si specifica il caricamento eager per una proprietà di navigazione impostando la Include proprietà del EntityDataSource controllo .

In Students.aspx si vuole mostrare il numero di corsi per ogni studente, quindi il caricamento eager è la scelta migliore. Se si visualizzano tutti gli studenti, ma si mostra il numero di corsi solo per alcuni di essi (che richiederebbe la scrittura di codice oltre al markup), il caricamento differita potrebbe essere una scelta migliore.

Aprire o passare a Students.aspx, passare alla visualizzazione Progettazione , selezionare StudentsEntityDataSourcee nella finestra Proprietà impostare la proprietà Includi su StudentGrades. Se si desidera ottenere più proprietà di navigazione, è possibile specificare i nomi separati da virgole, ad esempio StudentGrades, Courses.

Immagine 19

Passare alla visualizzazione Origine . StudentsGridView Nel controllo, dopo l'ultimo asp:TemplateField elemento, aggiungere il nuovo campo modello seguente:

<asp:TemplateField HeaderText="Number of Courses">
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Eval("StudentGrades.Count") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

Nell'espressione Eval è possibile fare riferimento alla proprietà StudentGradesdi navigazione . Poiché questa proprietà contiene una raccolta, dispone di una Count proprietà che è possibile utilizzare per visualizzare il numero di corsi in cui viene registrato lo studente. In un'esercitazione successiva si vedrà come visualizzare i dati dalle proprietà di navigazione che contengono singole entità anziché raccolte. Si noti che non è possibile utilizzare BoundField elementi per visualizzare i dati dalle proprietà di navigazione.

Eseguire la pagina e ora viene visualizzato il numero di corsi a cui ogni studente è iscritto.

Screenshot della finestra di Internet Explorer, che mostra la visualizzazione Aggiungi nuovi studenti con il nome e la data di registrazione di John Smith compilati nei campi di testo.

Uso di un controllo DetailsView per inserire entità

Il passaggio successivo consiste nel creare una pagina con un DetailsView controllo che consente di aggiungere nuovi studenti. Chiudere il browser e quindi creare una nuova pagina Web usando la pagina master Site.Master . Assegnare alla pagina il nome StudentsAdd.aspx e quindi passare alla visualizzazione Origine .

Aggiungere il markup seguente per sostituire il markup esistente per il Content controllo denominato Content2:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Add New Students</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EnableInsert="True" EntitySetName="People">
    </asp:EntityDataSource>
    <asp:DetailsView ID="StudentsDetailsView" runat="server" 
        DataSourceID="StudentsEntityDataSource" AutoGenerateRows="False"
        DefaultMode="Insert">
        <Fields>
            <asp:BoundField DataField="FirstMidName" HeaderText="First Name" 
                SortExpression="FirstMidName" />
            <asp:BoundField DataField="LastName" HeaderText="Last Name" 
                SortExpression="LastName" />
            <asp:BoundField DataField="EnrollmentDate" HeaderText="Enrollment Date" 
                SortExpression="EnrollmentDate" />
             <asp:CommandField ShowInsertButton="True" />
       </Fields>
    </asp:DetailsView>
</asp:Content>

Questo markup crea un EntityDataSource controllo simile a quello creato in Students.aspx, ad eccezione del fatto che abilita l'inserimento. Come per il GridView controllo, i campi associati del DetailsView controllo vengono codificati esattamente come per un controllo dati che si connette direttamente a un database, ad eccezione del fatto che fanno riferimento alle proprietà dell'entità. In questo caso, il controllo viene usato solo per l'inserimento DetailsView di righe, quindi è stata impostata la modalità predefinita su Insert.

Eseguire la pagina e aggiungere un nuovo studente.

Screenshot della finestra di Internet Explorer, che mostra la visualizzazione Aggiungi nuovi studenti con il nome e la data di registrazione di John Smith compilati nei campi di testo.

Non verrà eseguita alcuna operazione dopo l'inserimento di un nuovo studente, ma se si esegue Students.aspx, verranno visualizzate le nuove informazioni sugli studenti.

Visualizzazione di dati in un elenco di Drop-Down

Nei passaggi seguenti si esegue il databinding di un DropDownList controllo a un set di entità usando un EntityDataSource controllo . In questa parte dell'esercitazione non si eseguiranno molte operazioni con questo elenco. Nelle parti successive, tuttavia, si userà l'elenco per consentire agli utenti di selezionare un reparto per visualizzare i corsi associati al reparto.

Creare una nuova pagina Web denominata Courses.aspx. Nella visualizzazione Origine aggiungere un'intestazione al Content controllo denominato Content2:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Courses by Department</h2>
</asp:Content>

Nella visualizzazione Progettazione aggiungere un EntityDataSource controllo alla pagina come in precedenza, ad eccezione di questa volta denominarlo DepartmentsEntityDataSource. Selezionare Reparti come valore EntitySetName e selezionare solo le proprietà DepartmentID e Name .

Immagine15

Dalla scheda Standard della Casella degli strumenti trascinare un DropDownList controllo nella pagina, denominarlo DepartmentsDropDownList, fare clic sullo smart tag e selezionare Scegli origine dati per avviare la Configurazione guidata origine dati.

Immagine16

Nel passaggio Scegliere un'origine dati selezionare DepartmentsEntityDataSource come origine dati, fare clic su Aggiorna schema e quindi selezionare Nome come campo dati per visualizzare e DepartmentID come campo dati valore. Fare clic su OK.

Immagine17

Il metodo usato per associare il controllo usando Entity Framework è uguale a quello di altri controlli origine dati ASP.NET ad eccezione delle entità e delle proprietà dell'entità.

Passare alla visualizzazione Origine e aggiungere "Selezionare un reparto:" immediatamente prima del DropDownList controllo.

Select a department:
    <asp:DropDownList ID="DropDownList1" runat="server" 
        DataSourceID="EntityDataSource1" DataTextField="Name" 
        DataValueField="DepartmentID">
    </asp:DropDownList>

Come promemoria, modificare il markup per il EntityDataSource controllo in questo momento sostituendo gli ConnectionString attributi e DefaultContainerName con un ContextTypeName="ContosoUniversity.DAL.SchoolEntities" attributo . È spesso consigliabile attendere fino a quando non è stato creato il controllo associato a dati collegato al controllo origine dati prima di modificare il markup del EntityDataSource controllo, perché dopo aver apportato la modifica, la finestra di progettazione non fornirà un'opzione Aggiorna schema nel controllo associato a dati.

Eseguire la pagina ed è possibile selezionare un reparto dall'elenco a discesa.

Screenshot della finestra del browser Internet Explorer, che mostra la visualizzazione Corsi per reparto con un menu a discesa per i reparti.

In questo modo viene completata l'introduzione all'uso del EntityDataSource controllo . L'utilizzo di questo controllo in genere non è diverso dall'uso di altri controlli origine dati ASP.NET, ad eccezione del fatto che si fa riferimento a entità e proprietà anziché a tabelle e colonne. L'unica eccezione è quando si vuole accedere alle proprietà di navigazione. Nell'esercitazione successiva si noterà che la sintassi usata con EntityDataSource il controllo potrebbe anche essere diversa da altri controlli origine dati quando si filtrano, raggruppano e ordinano i dati.