Tutorial: Implementieren der CRUD-Funktionalität mit dem Entity Framework in ASP.NET MVC

Im vorherigen Tutorial haben Sie eine MVC-Anwendung erstellt, die Daten mithilfe von Entity Framework (EF) 6 und SQL Server LocalDB speichert und anzeigt. In diesem Tutorial überprüfen und anpassen Sie den CRUD-Code (Erstellen, Lesen, Aktualisieren, Löschen), den das MVC-Gerüst automatisch für Sie in Controllern und Ansichten erstellt.

Hinweis

Es ist üblich, dass das Repositorymuster implementiert wird, um eine Abstraktionsebene zwischen Ihrem Controller und der Datenzugriffsebene zu erstellen. Um diese Tutorials einfach zu halten und sich auf die Verwendung von EF 6 selbst zu konzentrieren, verwenden sie keine Repositorys. Informationen zum Implementieren von Repositorys finden Sie unter ASP.NET Data Access Content Map.

Hier finden Sie Beispiele für die von Ihnen erstellten Webseiten:

Screenshot der Seite mit den Kursteilnehmerdetails.

Screenshot der Seite

Screenshot der Seite zum Löschen des Schülers

In diesem Tutorial:

  • Erstellen einer Detailseite
  • Aktualisieren der Seite „Erstellen“
  • Aktualisieren der HttpPost Edit-Methode
  • Aktualisieren der Seite „Delete“ (Löschen)
  • Schließen von Datenbankverbindungen
  • Behandeln von Transaktionen

Voraussetzungen

Erstellen einer Detailseite

Der Gerüstcode für die Seite Schüler Index hat die Enrollments Eigenschaft weggelassen, da diese Eigenschaft eine Auflistung enthält. Auf der Details Seite zeigen Sie den Inhalt der Auflistung in einer HTML-Tabelle an.

In Controllers\StudentController.cs verwendet die Aktionsmethode für die Details Ansicht die Find-Methode , um eine einzelne Student Entität abzurufen.

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);
}

Der Schlüsselwert wird als id Parameter an die -Methode übergeben und stammt aus Routendaten im Link Details auf der Seite Index.

Tipp: Routendaten

Routingdaten sind Daten, die der Modellbinder in einem URL-Segment gefunden hat, das in der Routingtabelle angegeben ist. Die Standardroute gibt beispielsweise , actionund id Segmente ancontroller:

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

In der folgenden URL wird die Standardroute als controller, als das action und 1 als der idzugeordnet. Dabei handelt es sich Instructor um Index Routendatenwerte.

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

?courseID=2021 ist ein Abfragezeichenfolgenwert. Der Modellbinder funktioniert auch, wenn Sie den id als Abfragezeichenfolgenwert übergeben:

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

Die URLs werden von ActionLink Anweisungen in der Razor-Ansicht erstellt. Im folgenden Code stimmt der id Parameter mit der Standardroute überein, sodass id den Routendaten hinzugefügt wird.

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

Stimmt im folgenden Code courseID nicht mit einem Parameter in der Standardroute überein, sodass er als Abfragezeichenfolge hinzugefügt wird.

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

So erstellen Sie die Seite "Details"

  1. Öffnen Sie Views\Student\Details.cshtml.

    Jedes Feld wird mit einem DisplayFor Hilfsprogramm angezeigt, wie im folgenden Beispiel gezeigt:

    <dt>
        @Html.DisplayNameFor(model => model.LastName)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.LastName)
    </dd>
    
  2. Fügen Sie nach dem EnrollmentDate Feld und unmittelbar vor dem schließenden </dl> Tag den hervorgehobenen Code hinzu, um eine Liste der Registrierungen anzuzeigen, wie im folgenden Beispiel gezeigt:

    <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>
    

    Wenn der Codeeinzug nach dem Einfügen des Codes falsch ist, drücken Sie STRG+K, STRG+D , um ihn zu formatieren.

    Dieser Code durchläuft die Entitäten in der Navigationseigenschaft Enrollments. Für jede Enrollment Entität in der Eigenschaft werden der Kurstitel und die Note angezeigt. Der Kurstitel wird von der Course Entität abgerufen, die in der Course Navigationseigenschaft der Enrollments Entität gespeichert ist. Alle diese Daten werden automatisch aus der Datenbank abgerufen, wenn sie benötigt werden. Mit anderen Worten, Sie verwenden hier das verzögerte Laden. Sie haben keine Eiferladung für die Courses Navigationseigenschaft angegeben, sodass die Registrierungen nicht in derselben Abfrage abgerufen wurden, die die Kursteilnehmer erhalten hat. Stattdessen wird beim ersten Versuch, auf die Enrollments Navigationseigenschaft zuzugreifen, eine neue Abfrage an die Datenbank gesendet, um die Daten abzurufen. Weitere Informationen zu verzögertem Laden und eifrigem Laden finden Sie im Tutorial Lesen verwandter Daten weiter unten in dieser Reihe.

  3. Öffnen Sie die Seite Details, indem Sie das Programm starten (STRG+F5), die Registerkarte Schüler auswählen und dann auf den Link Details für Alexander Carson klicken. (Wenn Sie STRG+ drückenF5, während die Datei Details.cshtml geöffnet ist, erhalten Sie einen HTTP 400-Fehler. Dies liegt daran, dass Visual Studio versucht, die Detailseite auszuführen, aber nicht über einen Link erreicht wurde, der den anzuzeigenden Kursteilnehmer angibt. Entfernen Sie in diesem Fall "Student/Details" aus der URL, und versuchen Sie es erneut, oder schließen Sie den Browser, klicken Sie mit der rechten Maustaste auf das Projekt, und klicken Sie aufIm Browser anzeigen>.)

    Die Liste der Kurse und Noten für den ausgewählten Kursteilnehmer wird angezeigt.

  4. Schließen Sie den Browser.

Aktualisieren der Seite „Erstellen“

  1. Ersetzen Sie in Controller\StudentController.cs die HttpPostAttributeCreate Aktionsmethode durch den folgenden Code. Dieser Code fügt einen try-catch Block hinzu und entfernt ID aus dem BindAttribute Attribut für die gerüstete Methode:

    [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);
    }
    

    Dieser Code fügt der Entität hinzu, die Student vom ASP.NET MVC-Modellbinder erstellt wurde, dem Students Entitätssatz und speichert dann die Änderungen in der Datenbank. Modellbinder bezieht sich auf die ASP.NET MVC-Funktionalität, die Ihnen das Arbeiten mit Daten erleichtert, die von einem Formular übermittelt werden. ein Modellbinder konvertiert gebuchte Formularwerte in CLR-Typen und übergibt sie in Parametern an die Aktionsmethode. In diesem Fall instanziiert der Modellbinder eine Student Entität für Sie mithilfe von Eigenschaftswerten aus der Form Auflistung.

    Sie haben ID das Bind-Attribut entfernt, da es sich um ID den Primärschlüsselwert handelt, der SQL Server automatisch festlegt, wenn die Zeile eingefügt wird. Die Eingabe des Benutzers legt den ID Wert nicht fest.

    Sicherheitswarnung: Das ValidateAntiForgeryToken Attribut hilft dabei, siteübergreifende Anforderungsfälschungsangriffe zu verhindern. Es erfordert eine entsprechende Html.AntiForgeryToken() Anweisung in der Ansicht, die Später angezeigt wird.

    Das Bind Attribut ist eine Möglichkeit, um in Erstellungsszenarien vor Überbuchungen zu schützen. Angenommen, die Student Entität enthält eine Secret Eigenschaft, die diese Webseite nicht festlegen soll.

    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; }
    }
    

    Selbst wenn Sie kein Feld auf der Webseite haben Secret , kann ein Hacker ein Tool wie Fiddler verwenden oder javaScript schreiben, um einen Secret Formularwert zu posten. Ohne das BindAttribute Attribut, das die Felder einschränkt, die der Modellbinder beim Erstellen einer Student instance verwendet, würde der Modellbinder diesen Secret Formularwert aufgreifen und zum Erstellen der Student Entität instance verwenden. Dann würde jeder beliebige Wert in Ihre Datenbank aktualisiert werden, den der Hacker für das Formularfeld Secret festlegt. Die folgende Abbildung zeigt das Fiddler-Tool, das das Secret Feld (mit dem Wert "OverPost") zu den gebuchten Formularwerten hinzufügt.

    Screenshot der Registerkarte

    Der Wert „OverPost“ würde dann erfolgreich der Eigenschaft Secret der eingefügten Zeile hinzugefügt werden, obwohl Sie nie beabsichtigt haben, dass die Webseite diese Eigenschaft festlegen kann.

    Es ist am besten, den Include Parameter mit dem Bind -Attribut zu verwenden, um Felder explizit aufzulisten. Es ist auch möglich, den Exclude Parameter zu verwenden, um Felder zu blockieren, die Sie ausschließen möchten. Der Grund dafür Include ist, dass das neue Feld nicht automatisch durch eine Liste geschützt wird, wenn Sie der Entität eine Exclude neue Eigenschaft hinzufügen.

    Sie können das Überposten in Bearbeitungsszenarien verhindern, indem Sie zuerst die Entität aus der Datenbank lesen und dann aufrufen TryUpdateModel, indem Sie eine Explizite Zulässige Eigenschaftenliste übergeben. Dies ist die Methode, die in diesen Tutorials verwendet wird.

    Eine alternative Möglichkeit zum Verhindern von Überposting, die von vielen Entwicklern bevorzugt wird, besteht darin, Ansichtsmodelle anstelle von Entitätsklassen mit Modellbindung zu verwenden. Schließen Sie nur die Eigenschaften in dem Ansichtsmodell ein, die Sie aktualisieren möchten. Kopieren Sie nach Abschluss des MVC-Modellbinders die Eigenschaften des Ansichtsmodells in die Entität instance, optional mithilfe eines Tools wie AutoMapper. Verwenden Sie db. Eintrag für die Entität instance, um ihren Status auf Unverändert festzulegen, und dann Eigenschaft("PropertyName") festzulegen. IsModified to true für jede Entitätseigenschaft, die im Ansichtsmodell enthalten ist. Diese Methode funktioniert sowohl im Bearbeitungsszenario als auch im Erstellungsszenario.

    Neben dem Bind -Attribut ist der try-catch Block die einzige Änderung, die Sie am Gerüstcode vorgenommen haben. Wenn eine Ausnahme abgefangen wird, die von DataException abgeleitet wird, während die Änderungen gespeichert werden, wird eine generische Fehlermeldung angezeigt. DataException-Ausnahmen werden manchmal durch etwas außerhalb der Anwendung ausgelöst, und nicht durch einen Programmierfehler. Es wird empfohlen, dass der Benutzer es erneut versucht. Zwar wird es in diesem Beispiel nicht implementiert, aber eine qualitätsorientierte Produktionsanwendung würde die Ausnahme protokollieren. Weitere Informationen finden Sie im Abschnitt Log for insight (Einblicke durch Protokollierung) im Artikel Monitoring and Telemetry (Building Real-World Cloud Apps with Azure) (Überwachung und Telemetrie (Erstellen von realitätsnahen Cloud-Apps mit Azure)).

    Der Code in Views\Student\Create.cshtml ähnelt dem, was Sie in Details.cshtml gesehen haben, mit dem Unterschied, dass EditorFor und ValidationMessageFor Hilfsprogramme für jedes Feld anstelle von DisplayForverwendet werden. Hier ist der entsprechende Code:

    <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 enthält @Html.AntiForgeryToken()auch , das mit dem ValidateAntiForgeryToken -Attribut im Controller funktioniert, um siteübergreifende Angriffe auf Anforderungsfälschungen zu verhindern.

    In Create.cshtml sind keine Änderungen erforderlich.

  2. Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte Kursteilnehmer auswählen und dann auf Neu erstellen klicken.

  3. Geben Sie Namen und ein ungültiges Datum ein, und klicken Sie auf Erstellen , um die Fehlermeldung anzuzeigen.

    Dies ist die standardmäßige serverseitige Überprüfung. In einem späteren Tutorial erfahren Sie, wie Sie Attribute hinzufügen, die Code für die clientseitige Validierung generieren. Der folgende hervorgehobene Code zeigt die Modellüberprüfung in der Create-Methode .

    if (ModelState.IsValid)
    {
        db.Students.Add(student);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    
  4. Ändern Sie das Datum in einen gültigen Wert und klicken auf Erstellen, damit der neue Student auf der Seite Index angezeigt wird.

  5. Schließen Sie den Browser.

Aktualisieren der HttpPost Edit-Methode

  1. Ersetzen Sie die HttpPostAttributeEdit Aktionsmethode durch den folgenden Code:

    [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);
    }
    

    Hinweis

    In Controllers\StudentController.cs verwendet die HttpGet Edit -Methode (die ohne das HttpPost -Attribut) die Find -Methode, um die ausgewählte Student Entität abzurufen, wie Sie in der Details -Methode gesehen haben. Sie müssen diese Methode nicht ändern.

    Diese Änderungen implementieren eine bewährte Sicherheitsmethode, um Überposting zu verhindern. The scaffolder hat ein Bind Attribut generiert und die vom Modellbinder erstellte Entität der Entität hinzugefügt, die mit einem Geänderten Flag festgelegt wurde. Dieser Code wird nicht mehr empfohlen, da das Bind Attribut alle bereits vorhandenen Daten in Feldern löscht, die Include nicht im Parameter aufgeführt sind. In Zukunft wird das MVC-Controllergerüst aktualisiert, sodass keine Attribute für Edit-Methoden generiert Bind werden.

    Der neue Code liest die vorhandene Entität und ruft auf, TryUpdateModel felder aus der Benutzereingabe in den bereitgestellten Formulardaten zu aktualisieren. Die automatische Änderungsnachverfolgung von Entity Framework legt das Flag EntityState.Modified für die Entität fest. Wenn die SaveChanges-Methode aufgerufen wird, bewirkt das Modified Flag, dass das Entity Framework SQL-Anweisungen erstellt, um die Datenbankzeile zu aktualisieren. Parallelitätskonflikte werden ignoriert, und alle Spalten der Datenbankzeile werden aktualisiert, einschließlich der Spalten, die der Benutzer nicht geändert hat. (In einem späteren Tutorial wird gezeigt, wie Parallelitätskonflikte behandelt werden. Wenn Sie nur einzelne Felder in der Datenbank aktualisieren möchten, können Sie die Entität auf EntityState.Unchanged festlegen und einzelne Felder auf EntityState.Modified festlegen.)

    Um eine Überpostung zu verhindern, werden die Felder, die von der Seite Bearbeiten aktualisiert werden sollen, in den TryUpdateModel Parametern aufgeführt. Derzeit sind keine zusätzlichen von Ihnen geschützten Felder vorhanden. Wenn Sie jedoch die Felder auflisten, die die Modellbindung binden soll, stellen Sie sicher, dass zukünftig hinzugefügte Felder automatisch geschützt sind, bis Sie sie explizit hier hinzufügen.

    Infolge dieser Änderungen ist die Methodensignatur der HttpPost Edit-Methode mit der HttpGet-Edit-Methode identisch. Daher haben Sie die Methode EditPost umbenannt.

    Tipp

    Entitätszustände und die Attach- und SaveChanges-Methoden

    Der Datenbankkontext verfolgt, ob die Entitäten im Arbeitsspeicher mit ihren entsprechenden Zeilen in der Datenbank synchronisiert sind. Diese Information bestimmt, was passiert, wenn Sie die Methode SaveChanges aufrufen. Wenn Sie beispielsweise eine neue Entität an die Add-Methode übergeben, wird der Status dieser Entität auf Addedfestgelegt. Wenn Sie dann die SaveChanges-Methode aufrufen, gibt der Datenbankkontext einen SQL-Befehl INSERT aus.

    Eine Entität kann sich in einem der folgenden Zustände befinden:

    • Added. Die Entität ist noch nicht in der Datenbank vorhanden. Die SaveChanges -Methode muss eine INSERT Anweisung ausgeben.
    • Unchanged. Die Methode SaveChanges muss nichts mit dieser Entität tun. Wenn Sie eine Entität aus der Datenbank lesen, beginnt die Entität mit diesem Status.
    • Modified. Einige oder alle Eigenschaftswerte der Entität wurden geändert. Die SaveChanges -Methode muss eine UPDATE Anweisung ausgeben.
    • Deleted. Die Entität wurde zum Löschen markiert. Die SaveChanges -Methode muss eine DELETE Anweisung ausgeben.
    • Detached. Die Entität wird nicht vom Datenbankkontext nachverfolgt.

    Statusänderungen werden in einer Desktop-App in der Regel automatisch festgelegt. In einem Desktoptyp einer Anwendung lesen Sie eine Entität und nehmen Änderungen an einigen eigenschaftenwerten vor. Dadurch wird der Entitätsstatus automatisch auf Modified festgelegt. Wenn Sie dann aufrufen SaveChanges, generiert Entity Framework eine SQL-Anweisung UPDATE , die nur die tatsächlichen Eigenschaften aktualisiert, die Sie geändert haben.

    Die nicht verbundene Natur von Web-Apps lässt diese fortlaufende Sequenz nicht zu. Der DbContext , der eine Entität liest, wird verworfen, nachdem eine Seite gerendert wurde. Wenn die HttpPostEdit Aktionsmethode aufgerufen wird, wird eine neue Anforderung gestellt und Sie verfügen über eine neue instance des DbContext. Daher müssen Sie den Entitätsstatus manuell auf Modified. Then festlegen, wenn Sie aufrufenSaveChanges, aktualisiert Das Entity Framework alle Spalten der Datenbankzeile, da der Kontext keine Möglichkeit hat, zu wissen, welche Eigenschaften Sie geändert haben.

    Wenn die SQL-Anweisung Update nur die Felder aktualisiert, die der Benutzer tatsächlich geändert hat, können Sie die ursprünglichen Werte in irgendeiner Weise speichern (z. B. ausgeblendete Felder), sodass sie verfügbar sind, wenn die HttpPostEdit Methode aufgerufen wird. Anschließend können Sie eine Student Entität mit den ursprünglichen Werten erstellen, die Methode mit dieser Attach ursprünglichen Version der Entität aufrufen, die Werte der Entität auf die neuen Werte aktualisieren und dann aufrufen SaveChanges. Weitere Informationen finden Sie unter Entitätszustände und SpeichernÄnderungen und lokale Daten.

    Der HTML- und Razor-Code in Views\Student\Edit.cshtml ähnelt dem, was Sie in Create.cshtml gesehen haben, und es sind keine Änderungen erforderlich.

  2. Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte Kursteilnehmer auswählen und dann auf einen Link Bearbeiten klicken.

  3. Ändern Sie einige der Daten, und klicken Sie auf Speichern. Die geänderten Daten werden auf der Seite Index angezeigt.

  4. Schließen Sie den Browser.

Aktualisieren der Seite „Delete“ (Löschen)

In Controllers\StudentController.cs verwendet der Vorlagencode für die HttpGetAttributeDelete -Methode die Find -Methode, um die ausgewählte Student Entität abzurufen, wie Sie in den Details Methoden und Edit gesehen haben. Allerdings müssen Sie dieser Methode und der dazugehörigen Ansicht einige Funktionen hinzufügen, um eine benutzerdefinierte Fehlermeldung zu implementieren, wenn der Aufruf von SaveChanges fehlschlägt.

Wie Sie bereits bei den Vorgängen zum Aktualisieren und Erstellen gesehen haben, benötigen Löschvorgänge zwei Aktionsmethoden. Die Methode, die als Antwort auf eine GET-Anforderung aufgerufen wird, zeigt eine Ansicht an, die dem Benutzer die Möglichkeit gibt, den Löschvorgang zu genehmigen oder abzubrechen. Wenn der Benutzer diesen Löschvorgang genehmigt, wird eine POST-Anforderung erstellt. Wenn dies geschieht, wird die HttpPostDelete -Methode aufgerufen, und dann führt diese Methode tatsächlich den Löschvorgang aus.

Sie fügen der HttpPostAttributeDelete -Methode einen try-catch Block hinzu, um alle Fehler zu behandeln, die beim Aktualisieren der Datenbank auftreten können. Wenn ein Fehler auftritt, ruft die HttpPostAttributeDelete -Methode die HttpGetAttributeDelete -Methode auf und übergibt ihr einen Parameter, der angibt, dass ein Fehler aufgetreten ist. Die HttpGetAttributeDelete -Methode zeigt dann die Bestätigungsseite zusammen mit der Fehlermeldung erneut an, sodass der Benutzer die Möglichkeit hat, den Vorgang abzubrechen oder erneut zu versuchen.

  1. Ersetzen Sie die HttpGetAttributeDelete Aktionsmethode durch den folgenden Code, der die Fehlerberichterstattung verwaltet:

    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);
    }
    

    Dieser Code akzeptiert einen optionalen Parameter , der angibt, ob die Methode nach einem Fehler beim Speichern von Änderungen aufgerufen wurde. Dieser Parameter ist false , wenn die HttpGetDelete -Methode ohne vorherigen Fehler aufgerufen wird. Wenn er von der HttpPostDelete -Methode als Reaktion auf einen Datenbankupdatefehler aufgerufen wird, ist true der Parameter und eine Fehlermeldung wird an die Ansicht übergeben.

  2. Ersetzen Sie die HttpPostAttributeDelete Aktionsmethode (mit dem Namen DeleteConfirmed) durch den folgenden Code, der den tatsächlichen Löschvorgang ausführt und alle Datenbankupdatefehler abfangen.

    [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");
    }
    

    Dieser Code ruft die ausgewählte Entität ab und ruft dann die Remove-Methode auf, um die status der Entität auf Deletedfestzulegen. Beim Aufruf von SaveChanges wird der SQL-Befehl DELETE generiert. Ebenfalls haben Sie den Namen der Aktionsmethode DeleteConfirmed auf Delete geändert. Der Gerüstcode namens die HttpPostDelete -Methode DeleteConfirmed , um der HttpPost Methode eine eindeutige Signatur zu verleihen. (Die CLR erfordert überladene Methoden, um unterschiedliche Methodenparameter zu haben.) Nachdem die Signaturen eindeutig sind, können Sie sich an die MVC-Konvention halten und denselben Namen für die HttpPost Methoden und HttpGet Löschmethoden verwenden.

    Wenn die Verbesserung der Leistung in einer Anwendung mit hohem Volumen Priorität hat, können Sie eine unnötige SQL-Abfrage zum Abrufen der Zeile vermeiden, indem Sie die Codezeilen ersetzen, die die Find Methoden und Remove aufrufen, durch den folgenden Code:

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

    Dieser Code instanziiert eine Student Entität nur unter Verwendung des Primärschlüsselwerts und legt dann den Entitätsstatus auf fest Deleted. Das ist alles, was Entity Framework benötigt, um die Entität löschen zu können.

    Wie bereits erwähnt, löscht die HttpGetDelete Methode die Daten nicht. Das Ausführen eines Löschvorgangs als Reaktion auf eine GET-Anforderung (bzw. das Ausführen eines Bearbeitungsvorgangs, eines Erstellungsvorgangs oder eines anderen Vorgangs, der Daten ändert) führt zu einem Sicherheitsrisiko. Weitere Informationen finden Sie unter ASP.NET MVC-Tipp #46 – Verwenden Sie keine Löschlinks, da sie Sicherheitslöcher im Blog von Stephen Walther erstellen.

  3. Fügen Sie in Views\Student\Delete.cshtml eine Fehlermeldung zwischen der h2 Überschrift und der h3 Überschrift hinzu, wie im folgenden Beispiel gezeigt:

    <h2>Delete</h2>
    <p class="error">@ViewBag.ErrorMessage</p>
    <h3>Are you sure you want to delete this?</h3>
    
  4. Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte Kursteilnehmer auswählen und dann auf einen Link Löschen klicken.

  5. Wählen Sie Löschen auf der Seite mit der Meldung Sind Sie sicher, dass Sie diese Löschen möchten?.

    Die Seite Index wird ohne den gelöschten Kursteilnehmer angezeigt. (Ein Beispiel für den Code zur Fehlerbehandlung in Aktion sehen Sie im Parallelitätstutorial.)

Schließen von Datenbankverbindungen

Um Datenbankverbindungen zu schließen und die darin enthaltenen Ressourcen so schnell wie möglich freizugeben, entsorgen Sie den Kontext instance, wenn Sie damit fertig sind. Aus diesem Grund stellt der Gerüstcode eine Dispose-Methode am Ende der StudentController Klasse in StudentController.cs bereit, wie im folgenden Beispiel gezeigt:

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

Die Basisklasse Controller implementiert bereits die IDisposable Schnittstelle. Daher fügt dieser Code der -Methode einfach eine Überschreibung hinzuDispose(bool), um den Kontext explizit instance zu entsorgen.

Behandeln von Transaktionen

Standardgemäß implementiert Entity Framework implizit Transaktionen. In Szenarien, in denen Sie Änderungen an mehreren Zeilen oder Tabellen vornehmen und dann aufrufen SaveChanges, stellt das Entity Framework automatisch sicher, dass alle Änderungen erfolgreich sind oder dass alle Änderungen fehlschlagen. Wenn ein Fehler auftritt, nachdem einige der Änderungen durchgeführt wurden, werden diese Änderungen automatisch zurückgesetzt. Szenarien, in denen Sie mehr Kontrolle benötigen, z. B. wenn Sie Vorgänge außerhalb von Entity Framework in eine Transaktion einbeziehen möchten, finden Sie unter Arbeiten mit Transaktionen.

Abrufen des Codes

Abgeschlossenes Projekt herunterladen

Zusätzliche Ressourcen

Sie verfügen jetzt über einen vollständigen Satz von Seiten, die einfache CRUD-Vorgänge für Student Entitäten ausführen. Sie haben MVC-Hilfsprogramme verwendet, um Benutzeroberflächenelemente für Datenfelder zu generieren. Weitere Informationen zu MVC-Hilfsprogrammen finden Sie unter Rendern eines Formulars mithilfe von HTML-Hilfsprogrammen (der Artikel gilt für MVC 3, ist aber weiterhin relevant für MVC 5).

Links zu anderen EF 6-Ressourcen finden Sie unter ASP.NET Datenzugriff – Empfohlene Ressourcen.

Nächste Schritte

In diesem Tutorial:

  • Seite "Details" erstellt
  • Die Seite „Erstellen“ aktualisiert
  • Die HttpPost Edit-Methode wurde aktualisiert.
  • Die Seite „Löschen“ aktualisiert
  • Datenbankverbindungen geschlossen
  • Verarbeitete Transaktionen

Fahren Sie mit dem nächsten Artikel fort, um zu erfahren, wie Sie dem Projekt Sortierung, Filterung und Paging hinzufügen.