Condividi tramite


Esercitazione: Implementare funzionalità CRUD con Entity Framework in ASP.NET MVC

Nell'esercitazione precedente è stata creata un'applicazione MVC che archivia e visualizza i dati usando Entity Framework (EF) 6 e SQL Server LocalDB. In questa esercitazione si esamina e si personalizza il codice di creazione, lettura, aggiornamento, eliminazione (CRUD) creato automaticamente dallo scaffolding MVC nei controller e nelle visualizzazioni.

Nota

È pratica comune implementare lo schema del repository per creare un livello di astrazione tra il controller e il livello di accesso ai dati. Per mantenere queste esercitazioni semplici e incentrate sull'insegnamento su come usare EF 6 stesso, non usano repository. Per informazioni su come implementare i repository, vedi la mappa del contenuto di accesso ai dati ASP.NET.

Ecco alcuni esempi delle pagine Web create:

Screenshot della pagina dei dettagli degli studenti.

Screenshot della pagina di creazione degli studenti.

Screenshot della pagina di eliminazione degli studenti.

In questa esercitazione:

  • Creare una pagina Dettagli
  • Aggiornare la pagina Create
  • Aggiornare il metodo HttpPost Edit
  • Aggiornare la pagina Delete (Elimina)
  • Chiudere le connessioni di database
  • Gestire le transazioni

Prerequisiti

Creare una pagina Dettagli

Il codice sottoposto a scaffolding per la pagina Students Index ha lasciato la Enrollments proprietà , perché tale proprietà contiene un insieme. Details Nella pagina verrà visualizzato il contenuto della raccolta in una tabella HTML.

In Controllers\StudentController.cs il metodo di azione per la Details visualizzazione usa il metodo Find per recuperare una singola Student entità.

public ActionResult Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Student student = db.Students.Find(id);
    if (student == null)
    {
        return HttpNotFound();
    }
    return View(student);
}

Il valore della chiave viene passato al metodo come id parametro e proviene dai dati di route nel collegamento ipertestuale Dettagli nella pagina Indice.

Suggerimento: Indirizzare i dati

I dati di route sono dati trovati dallo strumento di associazione di modelli in un segmento di URL specificato nella tabella di routing. Ad esempio, la route predefinita specifica controlleri segmenti , actione id :

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Nell'URL seguente la route predefinita viene mappata Instructor come controller, Index come action e 1 come id; si tratta di valori di dati di route.

http://localhost:1230/Instructor/Index/1?courseID=2021

?courseID=2021 è un valore della stringa di query. Lo strumento di associazione di modelli funzionerà anche se si passa come valore della id stringa di query:

http://localhost:1230/Instructor/Index?id=1&CourseID=2021

Gli URL vengono creati dalle ActionLink istruzioni nella visualizzazione Razor. Nel codice seguente il id parametro corrisponde alla route predefinita, quindi id viene aggiunto ai dati della route.

@Html.ActionLink("Select", "Index", new { id = item.PersonID  })

Nel codice courseID seguente non corrisponde a un parametro nella route predefinita, quindi viene aggiunto come stringa di query.

@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })

Per creare la pagina Dettagli

  1. Aprire Views\Student\Details.cshtml.

    Ogni campo viene visualizzato usando un DisplayFor helper, come illustrato nell'esempio seguente:

    <dt>
        @Html.DisplayNameFor(model => model.LastName)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.LastName)
    </dd>
    
  2. Dopo il EnrollmentDate campo e immediatamente prima del tag di chiusura </dl> , aggiungere il codice evidenziato per visualizzare un elenco di registrazioni, come illustrato nell'esempio seguente:

    <dt>
                @Html.DisplayNameFor(model => model.EnrollmentDate)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => model.EnrollmentDate)
            </dd>
            <dt>
                @Html.DisplayNameFor(model => model.Enrollments)
            </dt>
            <dd>
                <table class="table">
                    <tr>
                        <th>Course Title</th>
                        <th>Grade</th>
                    </tr>
                    @foreach (var item in Model.Enrollments)
                    {
                        <tr>
                            <td>
                                @Html.DisplayFor(modelItem => item.Course.Title)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Grade)
                            </td>
                        </tr>
                    }
                </table>
            </dd>
        </dl>
    </div>
    <p>
        @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
        @Html.ActionLink("Back to List", "Index")
    </p>
    

    Se il rientro del codice non è corretto dopo aver incollato il codice, premere CTRL+K, CTRL+D per formattarlo.

    Il codice esegue il ciclo nelle entità nella proprietà di navigazione Enrollments. Per ogni Enrollment entità nella proprietà, visualizza il titolo del corso e il voto. Il titolo del corso viene recuperato dall'entità Course archiviata nella Course proprietà di navigazione dell'entità Enrollments . Tutti questi dati vengono recuperati automaticamente dal database quando sono necessari. In altre parole, si usa il caricamento differita qui. Non è stato specificato il caricamento eager per la Courses proprietà di navigazione, quindi le registrazioni non sono state recuperate nella stessa query che ha ottenuto gli studenti. Al contrario, la prima volta che si tenta di accedere alla Enrollments proprietà di navigazione, viene inviata una nuova query al database per recuperare i dati. Altre informazioni sul caricamento differita e sul caricamento eager sono disponibili nell'esercitazione Lettura dei dati correlati più avanti in questa serie.

  3. Aprire la pagina Dettagli avviando il programma (CTRL+F5), selezionando la scheda Studenti e quindi facendo clic sul collegamento Dettagli per Alexander Carson. (Se si preme CTRL+F5 mentre il file Details.cshtml è aperto, viene visualizzato un errore HTTP 400. Ciò è dovuto al fatto che Visual Studio tenta di eseguire la pagina Dettagli, ma non è stato raggiunto da un collegamento che specifica lo studente da visualizzare. In tal caso, rimuovere "Student/Details" dall'URL e riprovare oppure chiudere il browser, fare clic con il pulsante destro del mouse sul progetto e scegliere Visualizza>visualizzazione nel browser.

    Viene visualizzato l'elenco dei corsi e dei voti per lo studente selezionato.

  4. Chiudere il browser.

Aggiornare la pagina Create

  1. In Controllers\StudentController.cs sostituire il HttpPostAttribute Create metodo action con il codice seguente. Questo codice aggiunge un try-catch blocco e rimuove ID dall'attributo BindAttribute per il metodo scaffolded:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student)
    {
        try
        {
            if (ModelState.IsValid)
            {
                db.Students.Add(student);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
        }
        catch (DataException /* dex */)
        {
            //Log the error (uncomment dex variable name and add a line here to write a log.
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
        }
        return View(student);
    }
    

    Questo codice aggiunge l'entità Student creata dal gestore di associazione di modelli MVC ASP.NET al Students set di entità e quindi salva le modifiche nel database. Lo strumento di associazione di modelli fa riferimento alla funzionalità MVC ASP.NET che semplifica l'uso dei dati inviati da un modulo. Un gestore di associazione di modelli converte i valori del modulo inviati in tipi CLR e li passa al metodo action nei parametri. In questo caso, lo strumento di associazione di modelli crea un'istanza di un'entità Student usando i valori delle proprietà della Form raccolta.

    È stato rimosso ID dall'attributo Bind perché ID è il valore della chiave primaria impostato automaticamente da SQL Server quando viene inserita la riga. L'input dell'utente non imposta il ID valore.

    Avviso di sicurezza: l'attributo ValidateAntiForgeryToken consente di evitare attacchi falsi alla richiesta intersito. Richiede un'istruzione corrispondente Html.AntiForgeryToken() nella visualizzazione, che verrà visualizzata più avanti.

    L'attributo Bind è un modo per proteggersi dall'over-post negli scenari di creazione. Si supponga, ad esempio, che l'entità Student includa una Secret proprietà che non si vuole impostare in questa pagina Web.

    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }
        public string Secret { get; set; }
    
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    

    Anche se non si dispone di un Secret campo nella pagina Web, un hacker potrebbe usare uno strumento come fiddler o scrivere un codice JavaScript per pubblicare un valore di Secret modulo. Senza l'attributo BindAttribute che limita i campi usati dallo strumento di associazione di modelli quando crea un'istanzaStudent, lo strumento di associazione di modelli rileverà tale Secret valore del modulo e lo userà per creare l'istanza dell'entitàStudent. Di conseguenza, qualsiasi valore specificato dall'hacker per il campo di modulo Secret verrebbe aggiornato nel database. L'immagine seguente mostra lo strumento fiddler che aggiunge il Secret campo (con il valore "OverPost") ai valori del modulo pubblicati.

    Screenshot che mostra la scheda Composer. Nell'angolo in alto a destra, Execute è cerchiato in rosso. Nell'angolo in basso a destra, Secret equals Over Post è cerchiato in rosso.

    Il valore "OverPost" verrebbe quindi aggiunto alla proprietà Secret della riga inserita, sebbene non sia prevista in alcun modo l'impostazione della proprietà da parte della pagina Web.

    È consigliabile usare il Include parametro con l'attributo Bind per elencare in modo esplicito i campi. È anche possibile usare il Exclude parametro per bloccare i campi da escludere. Il motivo Include è che quando si aggiunge una nuova proprietà all'entità, il nuovo campo non viene protetto automaticamente da un Exclude elenco.

    È possibile impedire l'overposting negli scenari di modifica leggendo prima l'entità dal database e quindi chiamando TryUpdateModel, passando un elenco esplicito di proprietà consentite. Questo è il metodo usato in queste esercitazioni.

    Un modo alternativo per evitare l'overposting preferito da molti sviluppatori consiste nell'usare modelli di visualizzazione anziché classi di entità con l'associazione di modelli. Includere solo le proprietà da aggiornare nel modello di visualizzazione. Al termine dell'associazione di modelli MVC, copiare le proprietà del modello di visualizzazione nell'istanza dell'entità, facoltativamente usando uno strumento come AutoMapper. Usare db. Voce nell'istanza dell'entità per impostarne lo stato su Unchanged e quindi impostare Property("PropertyName"). IsModified su true per ogni proprietà di entità inclusa nel modello di visualizzazione. Questo metodo funziona negli scenari di modifica e negli scenari di creazione.

    Oltre all'attributo Bind , il try-catch blocco è l'unica modifica apportata al codice con scaffolding. Se viene rilevata un'eccezione che deriva da DataException durante il salvataggio delle modifiche, viene visualizzato un messaggio di errore generico. Poiché le eccezioni DataException sono a volte causate da elementi esterni all'applicazione e non da un errore di programmazione, viene consigliato all'utente di riprovare. Sebbene non sia implementata in questo esempio, un'applicazione di controllo della qualità di produzione potrebbe registrare l'eccezione. Per altre informazioni, vedere la sezione Log for insight (Registrare informazioni dettagliate) in Monitoring and Telemetry (Building Real-World Cloud Apps with Azure) (Monitoraggio e telemetria (creazione di app cloud realistiche con Azure)).

    Il codice in Views\Student\Create.cshtml è simile a quello visualizzato in Details.cshtml, ad eccezione del fatto che EditorFor e ValidationMessageFor gli helper vengono usati per ogni campo invece di DisplayFor. Di seguito è riportato il codice pertinente.

    <div class="form-group">
        @Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>
    </div>
    

    Create.cshtml include @Html.AntiForgeryToken()anche , che funziona con l'attributo ValidateAntiForgeryToken nel controller per evitare attacchi falsi alla richiesta intersito.

    Non sono necessarie modifiche in Create.cshtml.

  2. Eseguire la pagina avviando il programma, selezionando la scheda Studenti e quindi facendo clic su Crea nuovo.

  3. Immettere i nomi e una data non valida e fare clic su Crea per visualizzare il messaggio di errore.

    Si tratta della convalida lato server che si ottiene per impostazione predefinita. In un'esercitazione successiva verrà illustrato come aggiungere attributi che generano codice per la convalida lato client. Il codice evidenziato seguente mostra il controllo di convalida del modello nel metodo Create .

    if (ModelState.IsValid)
    {
        db.Students.Add(student);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    
  4. Modificare la data impostando un valore valido e fare clic su Crea per visualizzare il nuovo studente nella pagina Index.

  5. Chiudere il browser.

Aggiornare il metodo HttpPost Edit

  1. Sostituire il HttpPostAttribute Edit metodo action con il codice seguente:

    [HttpPost, ActionName("Edit")]
    [ValidateAntiForgeryToken]
    public ActionResult EditPost(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        var studentToUpdate = db.Students.Find(id);
        if (TryUpdateModel(studentToUpdate, "",
           new string[] { "LastName", "FirstMidName", "EnrollmentDate" }))
        {
            try
            {
                db.SaveChanges();
    
                return RedirectToAction("Index");
            }
            catch (DataException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }
        }
        return View(studentToUpdate);
    }
    

    Nota

    In Controllers\StudentController.cs il HttpGet Edit metodo (quello senza l'attributo HttpPost ) usa il Find metodo per recuperare l'entità selezionata Student , come illustrato nel Details metodo . Non è necessario modificare questo metodo.

    Queste modifiche implementano una procedura consigliata per la sicurezza per impedire l'overposting, lo scaffolder ha generato un Bind attributo e ha aggiunto l'entità creata dal gestore di associazione di modelli al set di entità con un flag Modificato. Questo codice non è più consigliato perché l'attributo Bind cancella tutti i dati preesistenti nei campi non elencati nel Include parametro . In futuro, lo scaffolder del controller MVC verrà aggiornato in modo che non generi Bind attributi per i metodi Edit.

    Il nuovo codice legge l'entità esistente e chiama TryUpdateModel per aggiornare i campi dall'input dell'utente nei dati del modulo inviati. Il rilevamento automatico delle modifiche di Entity Framework imposta il flag EntityState.Modified sull'entità. Quando viene chiamato il metodo SaveChanges , il Modified flag fa sì che Entity Framework crei istruzioni SQL per aggiornare la riga del database. I conflitti di concorrenza vengono ignorati e tutte le colonne della riga del database vengono aggiornate, incluse quelle che l'utente non ha modificato. (Un'esercitazione successiva illustra come gestire i conflitti di concorrenza e, se si vuole aggiornare solo i singoli campi nel database, è possibile impostare l'entità su EntityState.Unchanged e impostare i singoli campi su EntityState.Modified.

    Per evitare l'overposting, i campi che si desidera aggiornare dalla pagina Modifica sono elencati nei TryUpdateModel parametri. Sebbene attualmente non siano presenti campi aggiuntivi da proteggere, la creazione di un elenco dei campi che devono essere associati dallo strumento di associazione di modelli garantisce che eventuali campi aggiunti in seguito al modello di dati vengano protetti automaticamente fino a quando non vengono aggiunti in modo esplicito in questa posizione.

    In seguito a queste modifiche, la firma del metodo httpPost Edit equivale al metodo di modifica HttpGet; è stato quindi rinominato il metodo EditPost.

    Suggerimento

    Stati dell'entità e metodi Attach e SaveChanges

    Il contesto del database rileva se le entità in memoria sono sincronizzate con le righe corrispondenti nel database e queste informazioni determinano le operazioni eseguite quando viene chiamato il metodo SaveChanges. Ad esempio, quando si passa una nuova entità al metodo Add , lo stato dell'entità viene impostato su Added. Quindi, quando si chiama il metodo SaveChanges , il contesto del database genera un comando SQL INSERT .

    Un'entità può essere in uno dei seguenti stati:

    • Added. L'entità non esiste ancora nel database. Il SaveChanges metodo deve emettere un'istruzione INSERT .
    • Unchanged. Il metodo SaveChanges non deve eseguire alcuna operazione con l'entità. Quando un'entità viene letta dal database, l'entità ha inizialmente questo stato.
    • Modified. Sono stati modificati alcuni o tutti i valori di proprietà dell'entità. Il SaveChanges metodo deve emettere un'istruzione UPDATE .
    • Deleted. L'entità è stata contrassegnata per l'eliminazione. Il SaveChanges metodo deve emettere un'istruzione DELETE .
    • Detached. L'entità non viene registrata dal contesto del database.

    In un'applicazione desktop le modifiche dello stato vengono in genere impostate automaticamente. In un tipo di applicazione desktop si legge un'entità e si apportano modifiche ad alcuni dei relativi valori delle proprietà. In questo modo lo stato dell'entità viene modificato automaticamente in Modified. Quindi, quando si chiama SaveChanges, Entity Framework genera un'istruzione SQL UPDATE che aggiorna solo le proprietà effettive modificate.

    La natura disconnessa delle app Web non consente questa sequenza continua. DbContext che legge un'entità viene eliminata dopo il rendering di una pagina. Quando viene chiamato il HttpPost Edit metodo di azione, viene effettuata una nuova richiesta e si dispone di una nuova istanza di DbContext, quindi è necessario impostare manualmente lo stato Modified. dell'entità su Then quando si chiama SaveChanges, Entity Framework aggiorna tutte le colonne della riga del database, perché il contesto non è in grado di conoscere le proprietà modificate.

    Se si desidera che l'istruzione SQL Update aggiorni solo i campi effettivamente modificati dall'utente, è possibile salvare i valori originali in qualche modo (ad esempio i campi nascosti) in modo che siano disponibili quando viene chiamato il HttpPost Edit metodo . È quindi possibile creare un'entità Student usando i valori originali, chiamare il Attach metodo con la versione originale dell'entità, aggiornare i valori dell'entità ai nuovi valori e quindi chiamare SaveChanges. Per altre informazioni, vedere Stati entità e SaveChanges e Dati locali.

    Il codice HTML e Razor in Views\Student\Edit.cshtml è simile a quello visualizzato in Create.cshtml e non sono necessarie modifiche.

  2. Eseguire la pagina avviando il programma, selezionando la scheda Studenti e quindi facendo clic su un collegamento ipertestuale Modifica .

  3. Modificare alcuni dati e fare clic su Salva. I dati modificati sono visualizzati nella pagina Indice.

  4. Chiudere il browser.

Aggiornare la pagina Delete (Elimina)

In Controllers\StudentController.cs il codice del modello per il HttpGetAttribute Delete metodo usa il Find metodo per recuperare l'entità selezionata Student , come illustrato nei Details metodi e Edit . Tuttavia, per implementare un messaggio di errore personalizzato quando la chiamata di SaveChanges ha esito negativo, verrà aggiunta una funzionalità al metodo e alla visualizzazione corrispondente.

Analogamente alle operazioni di aggiornamento e creazione, le operazioni di eliminazione richiedono due metodi di azione. Il metodo chiamato in risposta a una richiesta GET visualizza una visualizzazione che consente all'utente di approvare o annullare l'operazione di eliminazione. Se l'utente approva, viene creata una richiesta POST. In questo caso, viene chiamato il HttpPost Delete metodo e quindi il metodo esegue effettivamente l'operazione di eliminazione.

Si aggiungerà un try-catch blocco al HttpPostAttribute Delete metodo per gestire eventuali errori che potrebbero verificarsi quando il database viene aggiornato. Se si verifica un errore, il HttpPostAttribute Delete metodo chiama il HttpGetAttribute Delete metodo , passandolo un parametro che indica che si è verificato un errore. Il HttpGetAttribute Delete metodo visualizza quindi nuovamente la pagina di conferma insieme al messaggio di errore, dando all'utente l'opportunità di annullare o riprovare.

  1. Sostituire il HttpGetAttribute Delete metodo action con il codice seguente, che gestisce la segnalazione degli errori:

    public ActionResult Delete(int? id, bool? saveChangesError=false)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        if (saveChangesError.GetValueOrDefault())
        {
            ViewBag.ErrorMessage = "Delete failed. Try again, and if the problem persists see your system administrator.";
        }
        Student student = db.Students.Find(id);
        if (student == null)
        {
            return HttpNotFound();
        }
        return View(student);
    }
    

    Questo codice accetta un parametro facoltativo che indica se il metodo è stato chiamato dopo un errore di salvataggio delle modifiche. Questo parametro si verifica false quando il HttpGet Delete metodo viene chiamato senza un errore precedente. Quando viene chiamato dal HttpPost Delete metodo in risposta a un errore di aggiornamento del database, il parametro è true e viene passato un messaggio di errore alla vista.

  2. Sostituire il HttpPostAttribute Delete metodo di azione (denominato DeleteConfirmed) con il codice seguente, che esegue l'operazione di eliminazione effettiva e rileva eventuali errori di aggiornamento del database.

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Delete(int id)
    {
        try
        {
            Student student = db.Students.Find(id);
            db.Students.Remove(student);
            db.SaveChanges();
        }
        catch (DataException/* dex */)
        {
            //Log the error (uncomment dex variable name and add a line here to write a log.
            return RedirectToAction("Delete", new { id = id, saveChangesError = true });
        }
        return RedirectToAction("Index");
    }
    

    Questo codice recupera l'entità selezionata, quindi chiama il metodo Remove per impostare lo stato dell'entità su Deleted. Quando SaveChanges viene chiamato, viene generato un comando SQL DELETE . Anche il nome del metodo di azione è stato modificato da DeleteConfirmed a Delete. Codice con scaffolding denominato il HttpPost Delete metodo per assegnare al HttpPost metodo DeleteConfirmed una firma univoca. CLR richiede metodi di overload per avere parametri di metodo diversi. Ora che le firme sono univoche, è possibile attenersi alla convenzione MVC e usare lo stesso nome per i HttpPost metodi ed HttpGet delete.

    Se il miglioramento delle prestazioni in un'applicazione con volumi elevati è una priorità, è possibile evitare una query SQL non necessaria per recuperare la riga sostituendo le righe di codice che chiamano i Find metodi e Remove con il codice seguente:

    Student studentToDelete = new Student() { ID = id };
    db.Entry(studentToDelete).State = EntityState.Deleted;
    

    Questo codice crea un'istanza di un'entità Student usando solo il valore della chiave primaria e quindi imposta lo stato dell'entità su Deleted. Questo è tutto ciò di cui Entity Framework necessita per eliminare l'entità.

    Come indicato, il HttpGet Delete metodo non elimina i dati. L'esecuzione di un'operazione di eliminazione in risposta a una richiesta GET (o per tale questione, l'esecuzione di qualsiasi operazione di modifica, l'operazione di creazione o qualsiasi altra operazione che modifica i dati) crea un rischio per la sicurezza.

  3. In Views\Student\Delete.cshtml aggiungere un messaggio di errore tra l'intestazione h2 e l'intestazione h3 , come illustrato nell'esempio seguente:

    <h2>Delete</h2>
    <p class="error">@ViewBag.ErrorMessage</p>
    <h3>Are you sure you want to delete this?</h3>
    
  4. Eseguire la pagina avviando il programma, selezionando la scheda Studenti e quindi facendo clic su un collegamento ipertestuale Elimina .

  5. Scegliere Elimina nella pagina in cui è indicato Eliminare?

    La pagina Indice viene visualizzata senza lo studente eliminato. Nell'esercitazione sulla concorrenza verrà visualizzato un esempio del codice di gestione degli errori in azione.

Chiudere le connessioni di database

Per chiudere le connessioni al database e liberare le risorse che contengono il prima possibile, eliminare l'istanza del contesto al termine dell'operazione. Ecco perché il codice con scaffolding fornisce un metodo Dispose alla fine della StudentController classe in StudentController.cs, come illustrato nell'esempio seguente:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        db.Dispose();
    }
    base.Dispose(disposing);
}

La classe base Controller implementa già l'interfaccia IDisposable , quindi questo codice aggiunge semplicemente un override al Dispose(bool) metodo per eliminare in modo esplicito l'istanza del contesto.

Gestire le transazioni

Per impostazione predefinita Entity Framework implementa in modo implicito le transazioni. Negli scenari in cui si apportano modifiche a più righe o tabelle e quindi si chiama SaveChanges, Entity Framework verifica automaticamente che tutte le modifiche abbiano esito positivo o negativo. Se sono state apportate alcune modifiche e successivamente si verifica un errore, viene automaticamente eseguito il rollback di tali verifiche. Per gli scenari in cui è necessario un maggiore controllo, ad esempio se si desidera includere operazioni eseguite all'esterno di Entity Framework in una transazione, vedere Uso delle transazioni.

Ottenere il codice

Scaricare il progetto completato

Risorse aggiuntive

È ora disponibile un set completo di pagine che eseguono semplici operazioni CRUD per Student le entità. Sono stati usati helper MVC per generare elementi dell'interfaccia utente per i campi dati. Per altre informazioni sugli helper MVC, vedi Rendering di un modulo con helper HTML (l'articolo è relativo a MVC 3, ma è ancora rilevante per MVC 5).

I collegamenti ad altre risorse di EF 6 sono disponibili in ASP.NET Accesso ai dati - Risorse consigliate.

Passaggi successivi

In questa esercitazione:

  • Pagina Dettagli creata
  • Aggiornamento della pagina Create
  • Aggiornamento del metodo HttpPost Edit
  • Aggiornare la pagina Delete
  • Chiusura delle connessioni di database
  • Transazioni gestite

Passare all'articolo successivo per informazioni su come aggiungere ordinamento, filtro e paging al progetto.