Lernprogramm: Implementieren der CRUD-Funktionalität mit dem Entity Framework in ASP.NET MVC
Im vorherigen Lernprogramm haben Sie eine MVC-Anwendung erstellt, die Daten mithilfe von Entity Framework (EF) 6 und SQL Server LocalDB speichert und anzeigt. In diesem Lernprogramm überprüfen und anpassen Sie den Code zum Erstellen, Lesen, Aktualisieren, Löschen (CRUD), 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 Lernprogramme 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 in der ASP.NET Inhaltszuordnung für den Datenzugriff.
Hier sind Beispiele für die webseiten, die Sie erstellen:
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 "Kursteilnehmer Index
" hat die Enrollments
Eigenschaft ausgelassen, 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 Indexseite.
Tipp: Routen von Daten
Routingdaten sind Daten, die der Modellordner in einem URL-Segment gefunden hat, das in der Routingtabelle angegeben ist. Die Standardroute gibt z. B. , action
und 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 Instructor
die Standardroute als die controller
und Index
1 als die action
id
; dies sind Routendatenwerte.
http://localhost:1230/Instructor/Index/1?courseID=2021
?courseID=2021
ist ein Abfragezeichenfolgenwert. Der Modellordner funktioniert auch, wenn Sie den id
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 entspricht der id
Parameter der Standardroute, wird also id
den Routendaten hinzugefügt.
@Html.ActionLink("Select", "Index", new { id = item.PersonID })
Im folgenden Code courseID
stimmt er nicht mit einem Parameter in der Standardroute überein, daher wird er als Abfragezeichenfolge hinzugefügt.
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
So erstellen Sie die Seite "Details"
Öffnen Sie "Views\Student\Details.cshtml".
Jedes Feld wird mithilfe eines
DisplayFor
Hilfsfelds angezeigt, wie im folgenden Beispiel gezeigt:<dt> @Html.DisplayNameFor(model => model.LastName) </dt> <dd> @Html.DisplayFor(model => model.LastName) </dd>
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 jedeEnrollment
Entität in der Eigenschaft werden der Kurstitel und die Noten angezeigt. Der Kurstitel wird von derCourse
Entität abgerufen, die in derCourse
Navigationseigenschaft derEnrollments
Entität gespeichert ist. Alle diese Daten werden automatisch aus der Datenbank abgerufen, wenn sie benötigt werden. Mit anderen Worten, Sie verwenden faules Laden hier. Sie haben kein begieriges Laden für dieCourses
Navigationseigenschaft angegeben, sodass die Registrierungen nicht in derselben Abfrage abgerufen wurden, die die Kursteilnehmer erhalten hat. Stattdessen wird beim ersten Versuch, auf dieEnrollments
Navigationseigenschaft zuzugreifen, eine neue Abfrage an die Datenbank gesendet, um die Daten abzurufen. Weitere Informationen zum faulen Laden und eifrigen Laden finden Sie im Lernprogramm "Lesen verwandter Daten " weiter unten in dieser Reihe.Öffnen Sie die Seite "Details", indem Sie das Programm (STRG+F5) starten, die Registerkarte "Kursteilnehmer " auswählen und dann auf den Link "Details " für Alexander Carson klicken. (Wenn Sie STRG+F5, während die Datei "Details.cshtml" geöffnet ist, wird ein HTTP 400-Fehler angezeigt. Dies liegt daran, dass Visual Studio versucht, die Seite "Details" auszuführen, aber nicht über einen Link erreicht wurde, der den anzuzeigenden Kursteilnehmer angibt. Entfernen Sie in diesem Fall "Schüler/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 dann im Browser auf "Ansicht anzeigen>".)
Die Liste der Kurse und Noten für den ausgewählten Kursteilnehmer wird angezeigt.
Schließen Sie den Browser.
Aktualisieren der Seite „Erstellen“
Ersetzen Sie in Controller\StudentController.cs die HttpPostAttribute
Create
Aktionsmethode durch den folgenden Code. Dieser Code fügt einentry-catch
Block hinzu und entferntID
aus dem BindAttribute Attribut für die Gerüstmethode:[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 die
Student
entität, die vom ASP.NET MVC-Modellbinder erstellt wurde, zumStudents
Entitätssatz hinzu und speichert dann die Änderungen in der Datenbank. Modellbinder bezieht sich auf die ASP.NET MVC-Funktionalität, die es Ihnen erleichtert, mit daten zu arbeiten, die von einem Formular übermittelt werden. Ein Modellordner konvertiert gepostete Formularwerte in CLR-Typen und übergibt sie an die Aktionsmethode in Parameter. In diesem Fall instanziiert der Modellbinder eineStudent
Entität für Sie mithilfe von Eigenschaftswerten aus derForm
Auflistung.Sie haben das Bind-Attribut entfernt
ID
, daID
es sich um den Primärschlüsselwert handelt, den SQL Server beim Einfügen der Zeile automatisch festlegt. Die Eingabe des Benutzers legt denID
Wert nicht fest.Sicherheitswarnung – Das
ValidateAntiForgeryToken
Attribut verhindert websiteübergreifende Fälschungsangriffe . Sie erfordert eine entsprechendeHtml.AntiForgeryToken()
Anweisung in der Ansicht, die Sie später sehen werden.Das
Bind
Attribut ist eine Möglichkeit, um vor Überbuchungen in Erstellungsszenarien zu schützen. Angenommen, dieStudent
Entität enthält eineSecret
Eigenschaft, die von dieser Webseite nicht festgelegt werden 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; } }
Auch wenn Sie kein Feld auf der Webseite haben
Secret
, könnte ein Hacker ein Tool wie Fiddler verwenden oder javaScript schreiben, um einenSecret
Formularwert zu veröffentlichen. Ohne das BindAttribute Attribut, das die Felder beschränkt, die der Modellordner beim Erstellen einerStudent
Instanz verwendet, würde der Modellordner diesenSecret
Formularwert aufnehmen und zum Erstellen der EntitätsinstanzStudent
verwenden. Dann würde jeder beliebige Wert in Ihre Datenbank aktualisiert werden, den der Hacker für das FormularfeldSecret
festlegt. Die folgende Abbildung zeigt das Fiddler-Tool, das dasSecret
Feld (mit dem Wert "OverPost") zu den geposteten Formularwerten hinzufügt.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 demBind
Attribut zum expliziten Auflisten von Feldern zu verwenden. Es ist auch möglich, den Parameter zum Blockieren vonExclude
Feldern zu verwenden, die Sie ausschließen möchten. Der GrundInclude
dafür ist, dass das neue Feld nicht automatisch durch eineExclude
Liste geschützt wird, wenn Sie der Entität eine neue Eigenschaft hinzufügen.Sie können das Überposten in Bearbeitungsszenarien verhindern, indem Sie zuerst die Entität aus der Datenbank lesen und dann eine explizite Liste zulässiger Eigenschaften übergeben
TryUpdateModel
. Dies ist die Methode, die in diesen Lernprogrammen verwendet wird.Eine alternative Möglichkeit zum Verhindern von Überpostungen, die von vielen Entwicklern bevorzugt werden, 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. Nachdem der MVC-Modellordner abgeschlossen ist, kopieren Sie die Ansichtsmodelleigenschaften in die Entitätsinstanz, optional mithilfe eines Tools wie AutoMapper. Verwenden Sie db. Eintrag in der Entitätsinstanz, um den Status auf "Unverändert" festzulegen, und legen Sie dann Property("PropertyName") fest. IsModified to true on each entity property that is included in the view model. Diese Methode funktioniert sowohl im Bearbeitungsszenario als auch im Erstellungsszenario.
Abgesehen vom
Bind
Attribut ist dertry-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, außer dass
EditorFor
undValidationMessageFor
Hilfsprogramme für jedes Feld anstelle vonDisplayFor
. 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 demValidateAntiForgeryToken
Attribut im Controller funktioniert, um websiteübergreifende Anforderungsverfälschungsangriffe zu verhindern.In Create.cshtml sind keine Änderungen erforderlich.
Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte "Kursteilnehmer" auswählen und dann auf "Neu erstellen" klicken.
Geben Sie Namen und ein ungültiges Datum ein, und klicken Sie auf " Erstellen ", um die Fehlermeldung anzuzeigen.
Dies ist die serverseitige Überprüfung, die Sie standardmäßig erhalten. In einem späteren Lernprogramm erfahren Sie, wie Sie Attribute hinzufügen, die Code für die clientseitige Überprüfung 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"); }
Ändern Sie das Datum in einen gültigen Wert und klicken auf Erstellen, damit der neue Student auf der Seite Index angezeigt wird.
Schließen Sie den Browser.
Update HttpPost Edit-Methode
Ersetzen Sie die HttpPostAttribute
Edit
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 methode ohne dasHttpPost
Attribut) dieFind
Methode, um die ausgewählteStudent
Entität abzurufen, wie Sie in derDetails
Methode gesehen haben. Sie müssen diese Methode nicht ändern.Diese Änderungen implementieren eine bewährte Methode zur Sicherheit, um die Überpostung zu verhindern, das Gerüst hat ein
Bind
Attribut generiert und die vom Modellordner erstellte Entität zur Entität hinzugefügt, die mit einem Geänderten Flag festgelegt wurde. Dieser Code wird nicht mehr empfohlen, da dasBind
Attribut bereits vorhandene Daten in Feldern löscht, dieInclude
nicht im Parameter aufgeführt sind. In Zukunft wird das MVC-Controllergerüst aktualisiert, sodass es keine Attribute für Edit-Methoden generiertBind
.Der neue Code liest die vorhandene Entität und Aufrufe TryUpdateModel zum Aktualisieren von Feldern von Benutzereingaben in den bereitgestellten Formulardaten. 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 derJenigen, die der Benutzer nicht geändert hat. (In einem späteren Lernprogramm wird gezeigt, wie Parallelitätskonflikte behandelt werden. Wenn nur einzelne Felder in der Datenbank aktualisiert werden sollen, können Sie die Entität aufEntityState.Unchanged and set individual fields to EntityState.Modified.)
Um das Überposten 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.Aufgrund dieser Änderungen ist die Methodensignatur der HttpPost Edit-Methode identisch mit der HttpGet-Bearbeitungsmethode; daher haben Sie die Methode EditPost umbenannt.
Tipp
Entitätszustände und die Methoden "Attach" und "SaveChanges"
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 "Added
. Wenn Sie dann die SaveChanges-Methode aufrufen, gibt der Datenbankkontext einen SQL-BefehlINSERT
aus.Eine Entität kann einen der folgenden Status aufweisen:
Added
. Die Entität ist in der Datenbank noch nicht vorhanden. DieSaveChanges
Methode muss eineINSERT
Anweisung ausgeben.Unchanged
. Die MethodeSaveChanges
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. DieSaveChanges
Methode muss eineUPDATE
Anweisung ausgeben.Deleted
. Die Entität wurde zum Löschen markiert. DieSaveChanges
Methode muss eineDELETE
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 der Anwendung lesen Sie eine Entität und nehmen Änderungen an einigen seiner Eigenschaftswerte vor. Dadurch wird der Entitätsstatus automatisch auf
Modified
festgelegt. Wenn Sie dann aufrufenSaveChanges
, generiert Das Entity Framework eine SQL-AnweisungUPDATE
, die nur die tatsächlichen Eigenschaften aktualisiert, die Sie geändert haben.Die getrennte Art von Web-Apps lässt diese fortlaufende Sequenz nicht zu. Der DbContext , der eine Entität liest, wird gelöscht, nachdem eine Seite gerendert wurde. Wenn die
HttpPost
Edit
Aktionsmethode aufgerufen wird, wird eine neue Anforderung gestellt, und Sie haben eine neue Instanz des DbContext, sodass Sie den EntitätsstatusModified.
manuell auf "Then" festlegen müssen, 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 aktualisieren soll, die der Benutzer tatsächlich geändert hat, können Sie die ursprünglichen Werte auf irgendeine Weise (z. B. ausgeblendete Felder) speichern, sodass sie beim Aufrufen derHttpPost
Edit
Methode verfügbar sind. Anschließend können Sie eineStudent
Entität mit den ursprünglichen Werten erstellen, die Methode mit dieserAttach
ursprünglichen Version der Entität aufrufen, die Werte der Entität auf die neuen Werte aktualisieren und dannSaveChanges.
weitere Informationen aufrufen, siehe Entitätszustände und SaveChanges 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.
Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte "Kursteilnehmer " auswählen und dann auf einen Link "Bearbeiten " klicken.
Ändern Sie einige der Daten, und klicken Sie auf Speichern. Die geänderten Daten werden auf der Indexseite angezeigt.
Schließen Sie den Browser.
Aktualisieren der Seite „Delete“ (Löschen)
In Controllers\StudentController.cs verwendet der Vorlagencode für die HttpGetAttribute Delete
Methode die Find
Methode, um die ausgewählte Student
Entität abzurufen, wie Sie in den Details
und Edit
den Methoden 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 Reaktion 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. In diesem Fall wird die HttpPost
Delete
Methode aufgerufen, und dann führt diese Methode tatsächlich den Löschvorgang aus.
Sie fügen der HttpPostAttribute Delete
Methode einen try-catch
Block hinzu, um alle Fehler zu behandeln, die auftreten können, wenn die Datenbank aktualisiert wird. Wenn ein Fehler auftritt, ruft die HttpPostAttribute Delete
Methode die HttpGetAttribute Delete
Methode auf und übergibt einen Parameter, der angibt, dass ein Fehler aufgetreten ist. Die HttpGetAttribute Delete
Methode zeigt dann die Bestätigungsseite zusammen mit der Fehlermeldung erneut an, sodass der Benutzer die Möglichkeit erhält, den Vorgang abzubrechen oder erneut zu versuchen.
Ersetzen Sie die HttpGetAttribute
Delete
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 wird
false
aufgerufen, wenn dieHttpGet
Delete
Methode ohne vorherigen Fehler aufgerufen wird. Wenn sie von derHttpPost
Delete
Methode als Reaktion auf einen Datenbankaktualisierungsfehler aufgerufen wird, wirdtrue
der Parameter und eine Fehlermeldung an die Ansicht übergeben.Ersetzen Sie die HttpPostAttribute
Delete
Aktionsmethode (benanntDeleteConfirmed
) durch den folgenden Code, der den tatsächlichen Löschvorgang ausführt, und erfasst alle Datenbankaktualisierungsfehler.[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 den Status der Entität auf festzulegen
Deleted
. Beim Aufruf vonSaveChanges
wird der SQL-BefehlDELETE
generiert. Ebenfalls haben Sie den Namen der AktionsmethodeDeleteConfirmed
aufDelete
geändert. Der Gerüstcode namens derHttpPost
Delete
Methode, um derHttpPost
MethodeDeleteConfirmed
eine eindeutige Signatur zu geben. (Die CLR erfordert überladene Methoden, um unterschiedliche Methodenparameter zu haben.) Nachdem die Signaturen eindeutig sind, können Sie mit der MVC-Konvention bleiben und denselben Namen für dieHttpPost
Methoden undHttpGet
Löschmethoden verwenden.Wenn es sich bei der Verbesserung der Leistung in einer Anwendung mit hohem Volumen um eine Priorität handelt, können Sie eine unnötige SQL-Abfrage vermeiden, um die Zeile abzurufen, indem Sie die Codezeilen ersetzen, die die
Find
UndRemove
Methoden durch den folgenden Code aufrufen:Student studentToDelete = new Student() { ID = id }; db.Entry(studentToDelete).State = EntityState.Deleted;
Dieser Code instanziiert eine
Student
Entität nur mit dem Primärschlüsselwert und legt dann den Entitätsstatus aufDeleted
. Das ist alles, was Entity Framework benötigt, um die Entität löschen zu können.Wie bereits erwähnt, löscht die
HttpGet
Delete
Methode die Daten nicht. Das Ausführen eines Löschvorgangs als Reaktion auf eine GET-Anforderung (oder für diese Frage, das Ausführen eines Bearbeitungsvorgangs, eines Erstellungsvorgangs oder eines anderen Vorgangs, der Daten ändert) führt zu einem Sicherheitsrisiko.Fügen Sie in Views\Student\Delete.cshtml eine Fehlermeldung zwischen der
h2
Überschrift und derh3
Ü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>
Führen Sie die Seite aus, indem Sie das Programm starten, die Registerkarte "Kursteilnehmer " auswählen und dann auf einen Link löschen klicken.
Wählen Sie "Löschen" auf der Seite mit der Meldung "Möchten Sie dies wirklich löschen?".
Die Indexseite wird ohne den gelöschten Kursteilnehmer angezeigt. (Im Parallelitätslernprogramm sehen Sie ein Beispiel für den Fehlerbehandlungscode in Aktion.)
Schließen von Datenbankverbindungen
Um Datenbankverbindungen zu schließen und die ressourcen freizugeben, die sie so schnell wie möglich enthalten, löschen Sie die Kontextinstanz, wenn Sie damit fertig sind. Aus diesem Grund stellt der Gerüstcode am Ende der StudentController
Klasse in StudentController.cs eine Dispose-Methode 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, sodass dieser Code der Methode einfach eine Außerkraftsetzung Dispose(bool)
hinzufügt, um die Kontextinstanz explizit zu löschen.
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 Ihre Änderungen erfolgreich sind oder alle 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 UI-Elemente für Datenfelder zu generieren. Weitere Informationen zu MVC-Hilfsern finden Sie unter Rendern eines Formulars mithilfe von HTML-Hilfselementen (der Artikel gilt für MVC 3, ist aber weiterhin für MVC 5 relevant).
Links zu anderen EF 6-Ressourcen finden Sie in ASP.NET Datenzugriff – Empfohlene Ressourcen.
Nächste Schritte
In diesem Tutorial haben Sie:
- Seite "Details" erstellt
- Die Seite „Erstellen“ aktualisiert
- Die HttpPost Edit-Methode wurde aktualisiert.
- Die Seite „Löschen“ aktualisiert
- Datenbankverbindungen geschlossen
- Verarbeitete Transaktionen
Wechseln Sie zum nächsten Artikel, um zu erfahren, wie Sie dem Projekt Sortier-, Filter- und Auslagerungen hinzufügen.