Einführung in ASP.NET Web Pages – Aktualisieren von Datenbankdaten
von Tom FitzMacken
In diesem Tutorial erfahren Sie, wie Sie einen vorhandenen Datenbankeintrag aktualisieren (ändern), wenn Sie ASP.NET Web Pages (Razor) verwenden. Es wird davon ausgegangen, dass Sie die Reihe durch Eingabe von Daten mithilfe von Formularen mithilfe von ASP.NET Web Pages abgeschlossen haben.
Sie lernen Folgendes:
- So wählen Sie einen einzelnen Datensatz im
WebGrid
Hilfsprogramm aus.- Lesen eines einzelnen Datensatzes aus einer Datenbank
- So laden Sie ein Formular mit Werten aus dem Datenbankdatensatz vorab.
- Aktualisieren eines vorhandenen Datensatzes in einer Datenbank
- So speichern Sie Informationen auf der Seite, ohne sie anzuzeigen.
- Verwenden eines ausgeblendeten Felds zum Speichern von Informationen
Beschriebene Features/Technologien:
- Das
WebGrid
Hilfsprogramm.- Der SQL-Befehl
Update
.- Die
Database.Execute
-Methode.- Ausgeblendete Felder (
<input type="hidden">
).
Sie lernen Folgendes
Im vorherigen Tutorial haben Sie gelernt, wie Sie einer Datenbank einen Datensatz hinzufügen. Hier erfahren Sie, wie Sie einen Datensatz zum Bearbeiten anzeigen. Auf der Seite Filme aktualisieren Sie das WebGrid
Hilfsprogramm, sodass neben jedem Film ein Link Bearbeiten angezeigt wird:
Wenn Sie auf den Link Bearbeiten klicken, gelangen Sie zu einer anderen Seite, auf der sich die Filminformationen bereits in einer Form befinden:
Sie können jeden der Werte ändern. Wenn Sie die Änderungen übermitteln, aktualisiert der Code auf der Seite die Datenbank und führt Sie zurück zur Filmliste.
Dieser Teil des Prozesses funktioniert fast genau wie die Seite "AddMovie.cshtml ", die Sie im vorherigen Tutorial erstellt haben, sodass ein Großteil dieses Tutorials vertraut ist.
Es gibt mehrere Möglichkeiten, einen einzelnen Film zu bearbeiten. Der gezeigte Ansatz wurde gewählt, weil er einfach zu implementieren und leicht zu verstehen ist.
Hinzufügen eines Bearbeitungslinks zum Filmeintrag
Zu Beginn aktualisieren Sie die Seite Filme , sodass jeder Filmeintrag auch einen Link zum Bearbeiten enthält.
Öffnen Sie die Datei Movies.cshtml .
Ändern Sie im Textkörper der Seite das WebGrid
Markup, indem Sie eine Spalte hinzufügen. Hier sehen Sie das geänderte Markup:
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
Die neue Spalte ist die folgende:
grid.Column(format: @<a href="~/EditMovie?id=@item.ID)">Edit</a>)
Der Punkt dieser Spalte besteht darin, einen Link (<a>
Element) anzuzeigen, dessen Text "Bearbeiten" lautet. Wir versuchen, einen Link zu erstellen, der wie folgt aussieht, wenn die Seite ausgeführt wird, wobei sich der id
Wert für jeden Film unterscheidet:
http://localhost:43097/EditMovie?id=7
Dieser Link ruft eine Seite mit dem Namen EditMovie auf, und die Abfragezeichenfolge ?id=7
wird an diese Seite übergeben.
Die Syntax für die neue Spalte mag etwas komplex aussehen, aber das liegt nur daran, dass sie mehrere Elemente enthält. Jedes einzelne Element ist einfach. Wenn Sie sich nur auf das <a>
Element konzentrieren, sehen Sie folgendes Markup:
<a href="~/EditMovie?id=@item.ID)">Edit</a>
Hintergrundinformationen zur Funktionsweise des Rasters: Das Raster zeigt Zeilen an, eine für jeden Datenbankdatensatz und Spalten für jedes Feld im Datenbankdatensatz. Während jede Rasterzeile erstellt wird, enthält das item
Objekt den Datenbankdatensatz (Element) für diese Zeile. Diese Anordnung gibt Ihnen eine Möglichkeit im Code, die Daten für diese Zeile abzurufen. Das sehen Sie hier: Der Ausdruck item.ID
erhält den ID-Wert des aktuellen Datenbankelements. Sie können alle Datenbankwerte (Titel, Genre oder Jahr) auf die gleiche Weise abrufen, indem Sie item.Title
, item.Genre
oder item.Year
verwenden.
Der Ausdruck "~/EditMovie?id=@item.ID
kombiniert den hartcodierten Teil der Ziel-URL (~/EditMovie?id=
) mit dieser dynamisch abgeleiteten ID. (Sie haben den ~
Operator im vorherigen Tutorial gesehen. Er ist ein ASP.NET-Operator, der den aktuellen Websitestamm darstellt.)
Das Ergebnis ist, dass dieser Teil des Markups in der Spalte einfach etwa das folgende Markup zur Laufzeit erzeugt:
href="/EditMovie?id=2"
Natürlich ist der tatsächliche Wert von id
für jede Zeile unterschiedlich.
Erstellen einer benutzerdefinierten Anzeige für eine Rasterspalte
Kehren Sie nun zur Rasterspalte zurück. Die drei Spalten, die sie ursprünglich im Raster hatten, wurden nur Datenwerte (Titel, Genre und Jahr) angezeigt. Sie haben diese Anzeige angegeben, indem Sie den Namen der Datenbankspalte übergeben, grid.Column("Title")
z. B. .
Diese neue Spalte Link bearbeiten unterscheidet sich. Anstatt einen Spaltennamen anzugeben, übergeben Sie einen format
Parameter. Mit diesem Parameter können Sie Markup definieren, das das WebGrid
Hilfsprogramm zusammen mit dem item
Wert rendert, um die Spaltendaten als fett oder grün oder in einem beliebigen Format anzuzeigen. Wenn Der Titel beispielsweise fett angezeigt werden soll, können Sie eine Spalte wie in diesem Beispiel erstellen:
grid.Column(format:@<strong>@item.Title</strong>)
(Die verschiedenen @
Zeichen, die in der format
Eigenschaft angezeigt werden, markieren den Übergang zwischen Markup und einem Codewert.)
Sobald Sie die format
Eigenschaft kennen, ist es einfacher zu verstehen, wie die neue Spalte Link bearbeiten zusammengestellt wird:
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
Die Spalte besteht nur aus dem Markup, das den Link rendert, sowie aus einigen Informationen (der ID), die aus dem Datenbankdatensatz für die Zeile extrahiert werden.
Tipp
Benannte Parameter und Positionsparameter für eine Methode
Viele Male, wenn Sie eine Methode aufgerufen und Parameter an sie übergeben haben, haben Sie einfach die Parameterwerte durch Kommas getrennt aufgelistet. Hier sind einige Beispiele angegeben:
db.Execute(insertCommand, title, genre, year)
Validation.RequireField("title", "You must enter a title")
Wir haben das Problem nicht Erwähnung, als Sie diesen Code zum ersten Mal gesehen haben, aber in jedem Fall übergeben Sie Parameter in einer bestimmten Reihenfolge an die Methoden – nämlich die Reihenfolge, in der die Parameter in dieser Methode definiert sind. Wenn Sie die Reihenfolge der übergebenen Werte für db.Execute
und Validation.RequireFields
vermischen, erhalten Sie eine Fehlermeldung, wenn die Seite ausgeführt wird, oder zumindest einige seltsame Ergebnisse. Natürlich müssen Sie die Reihenfolge kennen, um die Parameter zu übergeben. (In WebMatrix kann IntelliSense Ihnen helfen, den Namen, den Typ und die Reihenfolge der Parameter zu ermitteln.)
Alternativ zum Übergeben von Werten in der Reihenfolge können Sie benannte Parameter verwenden. (Das Übergeben von Parametern in der Reihenfolge wird als Verwendung von Positionsparametern bezeichnet.) Bei benannten Parametern geben Sie beim Übergeben des Werts explizit den Namen des Parameters an. In diesen Tutorials haben Sie bereits mehrfach benannte Parameter verwendet. Zum Beispiel:
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3)
und
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
Benannte Parameter sind für mehrere Situationen praktisch, insbesondere wenn eine Methode viele Parameter benötigt. Eine ist, wenn Sie nur ein oder zwei Parameter übergeben möchten, aber die Werte, die Sie übergeben möchten, gehören nicht zu den ersten Positionen in der Parameterliste. Eine andere Situation ist, wenn Sie Ihren Code lesbarer machen möchten, indem Sie die Parameter in der reihenfolge übergeben, die für Sie am sinnvollsten ist.
Um benannte Parameter zu verwenden, müssen Sie natürlich die Namen der Parameter kennen. WebMatrix IntelliSense kann Ihnen die Namen anzeigen , kann sie aber derzeit nicht für Sie ausfüllen.
Erstellen der Seite "Bearbeiten"
Jetzt können Sie die Seite EditMovie erstellen. Wenn Benutzer auf den Link Bearbeiten klicken, gelangen sie auf diese Seite.
Erstellen Sie eine Seite mit dem Namen EditMovie.cshtml , und ersetzen Sie die Datei durch das folgende Markup:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Movie</title>
<style>
.validation-summary-errors{
border:2px dashed red;
color:red;
font-weight:bold;
margin:12px;
}
</style>
</head>
<body>
<h1>Edit a Movie</h1>
@Html.ValidationSummary()
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@title" /></p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@genre" /></p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@year" /></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
</fieldset>
</form>
</body>
</html>
Dieses Markup und der Code ähneln dem, was Sie auf der AddMovie-Seite haben. Es gibt einen kleinen Unterschied im Text für die Schaltfläche "Senden". Wie bei der AddMovie-Seite gibt es einen Html.ValidationSummary
Aufruf, der Validierungsfehler anzeigt, falls vorhanden. Diesmal lassen wir Aufrufe von Validation.Message
aus, da Fehler in der Validierungszusammenfassung angezeigt werden. Wie im vorherigen Tutorial erwähnt, können Sie die Validierungszusammenfassung und die einzelnen Fehlermeldungen in verschiedenen Kombinationen verwenden.
Beachten Sie erneut, dass das method
Attribut des <form>
-Elements auf post
festgelegt ist. Wie bei der Seite AddMovie.cshtml nimmt diese Seite Änderungen an der Datenbank vor. Daher sollte dieses Formular einen POST
Vorgang ausführen. (Weitere Informationen zum Unterschied zwischen GET
vorgängen und POST
finden Sie in der Seitenleiste GET, POST und HTTP Verb Safety im Tutorial zu HTML-Formularen.)
Wie Sie in einem früheren Tutorial gesehen haben, werden die value
Attribute der Textfelder mit Razor-Code festgelegt, um sie vorab zu laden. Dieses Mal verwenden Sie jedoch Variablen wie title
und genre
für diese Aufgabe anstelle von Request.Form["title"]
:
<input type="text" name="title" value="@title" />
Wie zuvor wird dieses Markup die Textfeldwerte mit den Filmwerten vorab laden. Sie werden in einem Moment sehen, warum es praktisch ist, diesmal Variablen anstelle des Request
-Objekts zu verwenden.
Es gibt auch ein <input type="hidden">
Element auf dieser Seite. Dieses Element speichert die Film-ID, ohne sie auf der Seite sichtbar zu machen. Die ID wird zunächst mithilfe eines Abfragezeichenfolgenwerts (?id=7
oder ähnlich in der URL) an die Seite übergeben. Indem Sie den ID-Wert in ein ausgeblendetes Feld einfügen, können Sie sicherstellen, dass er verfügbar ist, wenn das Formular gesendet wird, auch wenn Sie keinen Zugriff mehr auf die ursprüngliche URL haben, mit der die Seite aufgerufen wurde.
Im Gegensatz zur AddMovie-Seite verfügt der Code für die Seite EditMovie über zwei unterschiedliche Funktionen. Die erste Funktion besteht darin, dass der Code die Film-ID aus der Abfragezeichenfolge abruft, wenn die Seite zum ersten Mal (und erst dann) angezeigt wird. Der Code verwendet dann die ID, um den entsprechenden Film aus der Datenbank zu lesen und ihn in den Textfeldern anzuzeigen (vorab zu laden).
Die zweite Funktion besteht darin, dass der Code, wenn der Benutzer auf die Schaltfläche Änderungen übermitteln klickt, die Werte der Textfelder lesen und überprüfen muss. Der Code muss auch das Datenbankelement mit den neuen Werten aktualisieren. Diese Technik ähnelt dem Hinzufügen eines Datensatzes, wie Sie in AddMovie gesehen haben.
Hinzufügen von Code zum Lesen eines einzelnen Films
Um die erste Funktion auszuführen, fügen Sie diesen Code oben auf der Seite hinzu:
@{
var title = "";
var genre = "";
var year = "";
var movieId = "";
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty()){
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was selected.");
}
}
}
Der größte Teil dieses Codes befindet sich in einem Block, der startet if(!IsPost)
. Der !
Operator bedeutet "nicht", also bedeutet der Ausdruck, ob es sich bei dieser Anforderung nicht um eine Postübermittlung handelt. Dies ist eine indirekte Möglichkeit, um zu sagen , ob diese Anforderung das erste Mal ist, dass diese Seite ausgeführt wird. Wie bereits erwähnt, sollte dieser Code nur bei der ersten Ausführung der Seite ausgeführt werden. Wenn Sie den Code nicht in if(!IsPost)
eingeschlossen haben, würde er jedes Mal ausgeführt, wenn die Seite aufgerufen wird, sei es beim ersten Mal oder als Reaktion auf einen Schaltflächenklick.
Beachten Sie, dass der Code dieses Mal einen else
Block enthält. Wie bei der Einführung von if
Blöcken bereits erwähnt, möchten Sie manchmal alternativen Code ausführen, wenn die von Ihnen getestete Bedingung nicht erfüllt ist. Das ist hier der Fall. Wenn die Bedingung besteht (d. h. wenn die an die Seite übergebene ID in Ordnung ist), lesen Sie eine Zeile aus der Datenbank. Wenn die Bedingung jedoch nicht besteht, wird der else
Block ausgeführt, und der Code legt eine Fehlermeldung fest.
Überprüfen eines an die Seite übergebenen Werts
Der Code verwendet Request.QueryString["id"]
, um die ID abzurufen, die an die Seite übergeben wird. Der Code stellt sicher, dass tatsächlich ein Wert für die ID übergeben wurde. Wenn kein Wert übergeben wurde, legt der Code einen Validierungsfehler fest.
Dieser Code zeigt eine andere Methode zum Überprüfen von Informationen. Im vorherigen Tutorial haben Sie mit dem Validation
Hilfsprogramm gearbeitet. Sie haben Felder registriert, um sie zu überprüfen, und ASP.NET die Überprüfung und die angezeigten Fehler automatisch mithilfe Html.ValidationMessage
von und Html.ValidationSummary
ausgeführt. In diesem Fall überprüfen Sie die Benutzereingabe jedoch nicht wirklich. Stattdessen überprüfen Sie einen Wert, der von einer anderen Stelle an die Seite übergeben wurde. Das Validation
tut der Helfer nicht für Sie.
Daher überprüfen Sie den Wert selbst, indem Sie ihn mit if(!Request.QueryString["ID"].IsEmpty()
testen. Wenn ein Problem vorliegt, können Sie den Fehler anzeigen Html.ValidationSummary
, indem Sie wie beim Validation
Hilfsprogramm verwenden. Dazu rufen Validation.AddFormError
Sie auf und übergeben ihr eine Meldung, die angezeigt werden soll. Validation.AddFormError
ist eine integrierte Methode, mit der Sie benutzerdefinierte Nachrichten definieren können, die mit dem Validierungssystem verknüpft sind, mit dem Sie bereits vertraut sind. (Weiter unten in diesem Tutorial erfahren Sie, wie Sie diesen Überprüfungsprozess etwas stabiler gestalten.)
Nachdem sichergestellt wurde, dass eine ID für den Film vorhanden ist, liest der Code die Datenbank und sucht nur nach einem einzelnen Datenbankelement. (Wahrscheinlich haben Sie das allgemeine Muster für Datenbankvorgänge bemerkt: Öffnen Sie die Datenbank, definieren Sie eine SQL-Anweisung, und führen Sie die Anweisung aus.) Dieses Mal enthält WHERE ID = @0
die SQL-Anweisung Select
. Da die ID eindeutig ist, kann nur ein Datensatz zurückgegeben werden.
Die Abfrage wird mithilfe db.QuerySingle
von ausgeführt (nicht db.Query
, wie Sie für die Filmauflistung verwendet haben), und der Code fügt das Ergebnis in die row
Variable ein. Der Name row
ist beliebig. Sie können die Variablen beliebig benennen. Die oben initialisierten Variablen werden dann mit den Filmdetails gefüllt, sodass diese Werte in den Textfeldern angezeigt werden können.
Testen der Seite "Bearbeiten" (Bisher)
Wenn Sie Ihre Seite testen möchten, führen Sie jetzt die Seite Filme aus, und klicken Sie neben einem beliebigen Film auf einen Link Bearbeiten . Die Seite EditMovie mit den Details für den ausgewählten Film wird angezeigt:
Beachten Sie, dass die URL der Seite etwas wie ?id=10
(oder eine andere Nummer) enthält. Bisher haben Sie getestet, ob Links auf der Seite Film bearbeiten funktionieren, dass Ihre Seite die ID aus der Abfragezeichenfolge liest und dass die Datenbankabfrage zum Abrufen eines einzelnen Filmdatensatzes funktioniert.
Sie können die Filminformationen ändern, aber nichts geschieht, wenn Sie auf Änderungen übermitteln klicken.
Hinzufügen von Code zum Aktualisieren des Films mit den Änderungen des Benutzers
Fügen Sie in der Datei EditMovie.cshtml den folgenden Code direkt innerhalb der schließenden Klammer des @
Blocks hinzu, um die zweite Funktion zu implementieren (Änderungen speichern). (Wenn Sie nicht genau wissen, wo der Code platziert werden soll, können Sie sich die vollständige Codeliste für die Seite Film bearbeiten ansehen, die am Ende dieses Tutorials angezeigt wird.)
if(IsPost){
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
Validation.RequireField("movieid", "No movie ID was submitted!");
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
movieId = Request.Form["movieId"];
if(Validation.IsValid()){
var db = Database.Open("WebPagesMovies");
var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
db.Execute(updateCommand, title, genre, year, movieId);
Response.Redirect("~/Movies");
}
}
Auch hier ähneln dieses Markup und der Code dem Code in AddMovie. Der Code befindet sich in einem if(IsPost)
-Block, da dieser Code nur ausgeführt wird, wenn der Benutzer auf die Schaltfläche "Änderungen senden " klickt, d. h. wenn (und nur, wenn das Formular gepostet wurde). In diesem Fall verwenden Sie keinen Test wie if(IsPost && Validation.IsValid())
, d. h. Sie kombinieren nicht beide Tests mithilfe von UND. Auf dieser Seite bestimmen Sie zunächst, ob eine Formularübermittlung vorhanden ist (if(IsPost)
), und registrieren erst dann die Felder für die Validierung. Anschließend können Sie die Validierungsergebnisse testen (if(Validation.IsValid()
). Der Flow unterscheidet sich geringfügig von der auf der Seite AddMovie.cshtml , aber der Effekt ist identisch.
Sie erhalten die Werte der Textfelder mithilfe Request.Form["title"]
von und ähnlichem Code für die anderen <input>
Elemente. Beachten Sie, dass der Code diesmal die Film-ID aus dem ausgeblendeten Feld (<input type="hidden">
) abruft. Wenn die Seite zum ersten Mal ausgeführt wurde, hat der Code die ID aus der Abfragezeichenfolge erhalten. Sie erhalten den Wert aus dem ausgeblendeten Feld, um sicherzustellen, dass Sie die ID des films erhalten, der ursprünglich angezeigt wurde, falls die Abfragezeichenfolge seitdem irgendwie geändert wurde.
Der wirklich wichtige Unterschied zwischen dem AddMovie-Code und diesem Code besteht darin, dass Sie in diesem Code die SQL-Anweisung Update
anstelle der Insert Into
-Anweisung verwenden. Das folgende Beispiel zeigt die Syntax der SQL-Anweisung Update
:
UPDATE table SET col1="value", col2="value", col3="value" ... WHERE ID = value
Sie können beliebige Spalten in beliebiger Reihenfolge angeben, und Sie müssen nicht unbedingt jede Spalte während eines Vorgangs Update
aktualisieren. (Sie können die ID selbst nicht aktualisieren, da dadurch der Datensatz tatsächlich als neuer Datensatz gespeichert würde und dies für einen Update
Vorgang nicht zulässig ist.)
Hinweis
Wichtig Die Where
-Klausel mit der ID ist sehr wichtig, da die Datenbank so weiß, welchen Datenbankdatensatz Sie aktualisieren möchten. Wenn Sie die Where
-Klausel ausgelassen haben, aktualisiert die Datenbank jeden Datensatz in der Datenbank. In den meisten Fällen wäre das eine Katastrophe.
Im Code werden die zu aktualisierenden Werte mithilfe von Platzhaltern an die SQL-Anweisung übergeben. Um zu wiederholen, was wir zuvor gesagt haben: Verwenden Sie aus Sicherheitsgründen nur Platzhalter, um Werte an eine SQL-Anweisung zu übergeben.
Nachdem der Code verwendet hat db.Execute
, um die Update
-Anweisung auszuführen, wird er zurück zur Eintragsseite weitergeleitet, auf der Sie die Änderungen sehen können.
Tipp
Verschiedene SQL-Anweisungen, unterschiedliche Methoden
Möglicherweise haben Sie bemerkt, dass Sie etwas unterschiedliche Methoden verwenden, um unterschiedliche SQL-Anweisungen auszuführen. Um eine Select
Abfrage auszuführen, die möglicherweise mehrere Datensätze zurückgibt, verwenden Sie die Query
-Methode. Um eine Select
Abfrage auszuführen, von der Sie wissen, dass sie nur ein Datenbankelement zurückgibt, verwenden Sie die QuerySingle
-Methode. Um Befehle auszuführen, die Änderungen vornehmen, aber keine Datenbankelemente zurückgeben, verwenden Sie die Execute
-Methode.
Sie müssen unterschiedliche Methoden haben, da jede von ihnen unterschiedliche Ergebnisse zurückgibt, wie Sie bereits im Unterschied zwischen Query
und QuerySingle
gesehen haben. (Die Execute
Methode gibt tatsächlich auch einen Wert zurück , nämlich die Anzahl der Datenbankzeilen, die vom Befehl betroffen waren, aber Sie haben diesen bisher ignoriert.)
Natürlich gibt die Query
-Methode möglicherweise nur eine Datenbankzeile zurück. Die Ergebnisse der Query
-Methode werden von ASP.NET jedoch immer als Sammlung behandelt. Auch wenn die Methode nur eine Zeile zurückgibt, müssen Sie diese einzelne Zeile aus der Auflistung extrahieren. Daher ist es in Situationen, in denen Sie wissen, dass Sie nur eine Zeile zurückbekommen, etwas bequemer, zu verwenden QuerySingle
.
Es gibt einige andere Methoden, die bestimmte Arten von Datenbankvorgängen ausführen. Eine Liste der Datenbankmethoden finden Sie in der ASP.NET Web Pages-API-Kurzreferenz.
Stabilere Überprüfung für die ID
Wenn die Seite zum ersten Mal ausgeführt wird, erhalten Sie die Film-ID aus der Abfragezeichenfolge, damit Sie diesen Film aus der Datenbank abrufen können. Sie haben sichergestellt, dass tatsächlich ein Wert vorhanden ist, nach dem gesucht werden muss, was Sie mithilfe des folgenden Codes getan haben:
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty()){
// Etc.
}
}
Sie haben diesen Code verwendet, um sicherzustellen, dass, wenn ein Benutzer auf die Seite EditMovies gelangt, ohne zuerst einen Film auf der Seite Filme auszuwählen, auf der Seite eine benutzerfreundliche Fehlermeldung angezeigt wird. (Andernfalls würden Benutzer einen Fehler sehen, der sie wahrscheinlich nur verwirren würde.)
Diese Überprüfung ist jedoch nicht sehr robust. Die Seite kann auch mit den folgenden Fehlern aufgerufen werden:
- Die ID ist keine Zahl. Beispielsweise könnte die Seite mit einer URL wie
http://localhost:nnnnn/EditMovie?id=abc
aufgerufen werden. - Die ID ist eine Zahl, verweist jedoch auf einen Film, der nicht vorhanden ist (z. B.
http://localhost:nnnnn/EditMovie?id=100934
).
Wenn Sie die Fehler sehen möchten, die sich aus diesen URLs ergeben, führen Sie die Seite Filme aus. Wählen Sie einen zu bearbeitenden Film aus, und ändern Sie dann die URL der EditMovie-Seite in eine URL, die eine alphabetische ID oder die ID eines nicht vorhandenen Films enthält.
Was sollten Sie also tun? Der erste Fix besteht darin, sicherzustellen, dass nicht nur eine ID an die Seite übergeben wird, sondern dass die ID eine ganze Zahl ist. Ändern Sie den Code für den !IsPost
Test so, dass er wie in diesem Beispiel aussieht:
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
// Etc.
Sie haben dem Test eine zweite Bedingung hinzugefügt, die IsEmpty
mit verknüpft ist &&
(logisches AND):
Request.QueryString["ID"].IsInt()
Vielleicht erinnern Sie sich aus dem Tutorial Einführung in ASP.NET Web Pages Programmierung, dass Methoden wie AsBool
eine AsInt
Zeichenfolge in einen anderen Datentyp konvertieren. Die IsInt
-Methode (und andere, wie IsBool
und IsDateTime
) sind ähnlich. Sie testen jedoch nur, ob Sie die Zeichenfolge konvertieren können , ohne die Konvertierung tatsächlich durchzuführen. Hier sagen Sie im Wesentlichen If the query string value can be converted to an integer ....
Das andere potenzielle Problem ist die Suche nach einem Film, der nicht existiert. Der Code zum Abrufen eines Films sieht wie folgt aus:
var row = db.QuerySingle(dbCommand, movieId);
Wenn Sie einen movieId
Wert an die -Methode übergeben, der QuerySingle
nicht einem tatsächlichen Film entspricht, wird nichts zurückgegeben, title=row.Title
und die folgenden Anweisungen (z. B. ) führen zu Fehlern.
Auch hier gibt es eine einfache Lösung. Wenn die db.QuerySingle
Methode keine Ergebnisse zurückgibt, ist die row
Variable NULL. Daher können Sie überprüfen, ob die row
Variable NULL ist, bevor Sie versuchen, Werte daraus abzurufen. Der folgende Code fügt einen if
Block um die -Anweisungen hinzu, die die Werte aus dem row
-Objekt abrufen:
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was found for that ID.");
}
Mit diesen beiden zusätzlichen Validierungstests wird die Seite aufzählungssicherer. Der vollständige Code für den !IsPost
Branch sieht nun wie in diesem Beispiel aus:
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else {
Validation.AddFormError("No movie was found for that ID.");
}
}
else {
Validation.AddFormError("No movie was selected.");
}
}
Wir werden noch einmal darauf hinweisen, dass diese Aufgabe eine gute Verwendung für einen else
Block ist. Wenn die Tests nicht erfolgreich sind, legen die else
Blöcke Fehlermeldungen fest.
Hinzufügen eines Links, um zur Seite "Filme" zurückzukehren
Ein letztes und hilfreiches Detail ist das Hinzufügen eines Links zurück zur Seite Filme . Im normalen Ablauf von Ereignissen beginnen Benutzer auf der Seite Filme und klicken auf einen Link Bearbeiten . Dadurch gelangen sie zur EditMovie-Seite , wo sie den Film bearbeiten und auf die Schaltfläche klicken können. Nachdem der Code die Änderung verarbeitet hat, wird er zurück zur Seite Filme umgeleitet.
Allerdings:
- Der Benutzer entscheidet sich möglicherweise, nichts zu ändern.
- Der Benutzer ist möglicherweise zu dieser Seite gelangt, ohne zuerst auf den Link Bearbeiten auf der Seite Filme zu klicken.
In beiden Richtungen möchten Sie es ihnen leicht machen, zum Standard-Eintrag zurückzukehren. Dies ist eine einfache Lösung: Fügen Sie das folgende Markup direkt nach dem schließenden </form>
Tag im Markup hinzu:
<p><a href="~/Movies">Return to movie listing</a></p>
Dieses Markup verwendet die gleiche Syntax für ein <a>
Element, das Sie an anderer Stelle gesehen haben. Die URL enthält ~
den Begriff "Stamm der Website".
Testen des Filmupdateprozesses
Jetzt können Sie testen. Führen Sie die Seite Filme aus, und klicken Sie neben einem Film auf Bearbeiten . Wenn die Seite EditMovie angezeigt wird, nehmen Sie Änderungen am Film vor, und klicken Sie auf Änderungen übermitteln. Wenn die Filmauflistung angezeigt wird, stellen Sie sicher, dass Ihre Änderungen angezeigt werden.
Um sicherzustellen, dass die Überprüfung funktioniert, klicken Sie für einen anderen Film auf Bearbeiten . Wenn Sie auf die Seite EditMovie gelangen, deaktivieren Sie das Feld Genre (oder das Feld Jahr oder beides), und versuchen Sie, Ihre Änderungen zu übermitteln. Es wird wie erwartet ein Fehler angezeigt:
Klicken Sie auf den Link Zurück zum Filmeintrag , um Ihre Änderungen aufzugeben und zur Seite Filme zurückzukehren.
Nächster Schritt
Im nächsten Tutorial erfahren Sie, wie Sie einen Filmdatensatz löschen.
Vollständige Auflistung der Filmseite (aktualisiert mit Links bearbeiten)
@{
var db = Database.Open("WebPagesMovies") ;
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";
if(!Request.QueryString["searchGenre"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
searchTerm = Request.QueryString["searchGenre"];
}
if(!Request.QueryString["searchTitle"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
}
var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Movies</title>
<style type="text/css">
.grid { margin: 4px; border-collapse: collapse; width: 600px; }
.grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
.head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
.alt { background-color: #E8E8E8; color: #000; }
</style>
</head>
<body>
<h1>Movies</h1>
<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>
<div>
<label for="SearchTitle">Movie title contains the following:</label>
<input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
<input type="Submit" value="Search Title" /><br/>
</div>
</form>
<div>
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
</div>
<p>
<a href="~/AddMovie">Add a movie</a>
</p>
</body>
</html>
Vollständige Seitenliste für die Seite "Film bearbeiten"
@{
var title = "";
var genre = "";
var year = "";
var movieId = "";
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was selected.");
}
}
else{
Validation.AddFormError("No movie was selected.");
}
}
if(IsPost){
Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");
Validation.RequireField("movieid", "No movie ID was submitted!");
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
movieId = Request.Form["movieId"];
if(Validation.IsValid()){
var db = Database.Open("WebPagesMovies");
var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
db.Execute(updateCommand, title, genre, year, movieId);
Response.Redirect("~/Movies");
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Movie</title>
<style>
.validation-summary-errors{
border:2px dashed red;
color:red;
font-weight:bold;
margin:12px;
}
</style>
</head>
<body>
<h1>Edit a Movie</h1>
@Html.ValidationSummary()
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><label for="title">Title:</label>
<input type="text" name="title" value="@title" /></p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@genre" /></p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@year" /></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
</fieldset>
</form>
<p><a href="~/Movies">Return to movie listing</a></p>
</body>
</html>
Zusätzliche Ressourcen
- Einführung in ASP.NET Webprogrammierung mithilfe der Razor-Syntax
- SQL UPDATE-Anweisung auf der W3Schools-Website