Wprowadzenie ASP.NET stron internetowych — usuwanie danych bazy danych
Autor: Tom FitzMacken
W tym samouczku pokazano, jak usunąć pojedynczy wpis bazy danych. Przyjęto założenie, że seria została ukończona za pośrednictwem aktualizowania danych bazy danych na ASP.NET stronach sieci Web.
Zawartość:
- Jak wybrać pojedynczy rekord z listy rekordów.
- Jak usunąć pojedynczy rekord z bazy danych.
- Jak sprawdzić, czy określony przycisk został kliknięty w formularzu.
Omówione funkcje/technologie:
- Pomocnik
WebGrid
.- Polecenie SQL
Delete
.- Metoda uruchamiania
Database.Execute
polecenia SQLDelete
.
Co utworzysz
W poprzednim samouczku przedstawiono sposób aktualizowania istniejącego rekordu bazy danych. Ten samouczek jest podobny, z tą różnicą, że zamiast aktualizować rekord, usuniesz go. Procesy są takie same, z tą różnicą, że usuwanie jest prostsze, więc ten samouczek będzie krótki.
Na stronie Filmy zaktualizujesz WebGrid
pomocnika, aby wyświetlił link Usuń obok każdego filmu, który będzie towarzyszyć dodanemu wcześniej linkowi Edytuj .
Podobnie jak w przypadku edytowania, po kliknięciu linku Usuń następuje przejście do innej strony, na której informacje o filmie są już w formularzu:
Następnie możesz kliknąć przycisk, aby trwale usunąć rekord.
Dodawanie linku usuwania do listy filmów
Zaczniesz od dodania linku WebGrid
Usuń do pomocnika. Ten link jest podobny do linku Edytuj dodanego w poprzednim samouczku.
Otwórz plik Movies.cshtml.
WebGrid
Zmień znaczniki w treści strony, dodając kolumnę. Oto zmodyfikowany znacznik:
@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"),
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
)
)
Nowa kolumna to ta:
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
Tak, jak jest skonfigurowana siatka, kolumna Edytuj znajduje się najdalej w siatce, a kolumna Usuń znajduje się w prawej części. (Teraz jest przecinek po kolumnie Year
, na wypadek gdyby tego nie zauważyliśmy). Nie ma nic specjalnego w tym, gdzie te kolumny linków idą, i można je tak łatwo umieścić obok siebie. W tym przypadku są one oddzielone, aby utrudnić im mieszanie się.
Nowa kolumna zawiera link (<a>
element), którego tekst to "Delete". Elementem docelowym linku (atrybutu href
) jest kod, który ostatecznie rozpoznaje coś podobnego do tego adresu URL, z wartością id
inną dla każdego filmu:
http://localhost:43097/DeleteMovie?id=7
Ten link spowoduje wywołanie strony o nazwie DeleteFilm i przekazanie jej identyfikatora wybranego filmu.
Ten samouczek nie zawiera szczegółowych informacji na temat sposobu konstruowania tego linku, ponieważ jest niemal identyczny z linkiem Edytuj z poprzedniego samouczka (Aktualizowanie danych bazy danych w ASP.NET stronach sieci Web).
Tworzenie strony usuwania
Teraz możesz utworzyć stronę, która będzie elementem docelowym linku Usuń w siatce.
Uwaga
Ważne Technika pierwszego wybierania rekordu do usunięcia, a następnie używania oddzielnej strony i przycisku w celu potwierdzenia, że proces jest niezwykle ważny w przypadku zabezpieczeń. Jak czytamy w poprzednich samouczkach, wszelkie zmiany w witrynie internetowej powinny być zawsze wykonywane przy użyciu formularza — czyli przy użyciu operacji POST protokołu HTTP. Jeśli umożliwisz zmianę witryny tylko po kliknięciu linku (czyli przy użyciu operacji GET), użytkownicy mogą wysyłać proste żądania do witryny i usuwać dane. Nawet przeszukiwarka aparatu wyszukiwania, która indeksuje witrynę, może przypadkowo usunąć dane, korzystając z poniższych linków.
Gdy aplikacja umożliwia użytkownikom zmianę rekordu, musisz mimo to przedstawić rekord użytkownikowi do edycji. Możesz jednak pominąć ten krok w celu usunięcia rekordu. Nie pomijaj jednak tego kroku. (Przydatne jest również, aby użytkownicy widzieli rekord i potwierdzili, że usuwają rekord, który mają zamierzyć).
W kolejnym zestawie samouczków zobaczysz, jak dodać funkcję logowania, aby użytkownik musiał się zalogować przed usunięciem rekordu.
Utwórz stronę o nazwie DeleteImage.cshtml i zastąp zawartość pliku następującym znacznikiem:
<html>
<head>
<title>Delete a Movie</title>
</head>
<body>
<h1>Delete a Movie</h1>
@Html.ValidationSummary()
<p><a href="~/Movies">Return to movie listing</a></p>
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><span>Title:</span>
<span>@title</span></p>
<p><span>Genre:</span>
<span>@genre</span></p>
<p><span>Year:</span>
<span>@year</span></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonDelete" value="Delete Movie" /></p>
</fieldset>
</form>
</body>
</html>
Ten znacznik przypomina strony EditFilm , z tą różnicą, że zamiast używać pól tekstowych (<input type="text">
), znacznik zawiera <span>
elementy. Nie ma tutaj nic do edycji. Wystarczy wyświetlić szczegóły filmu, aby użytkownicy mogli upewnić się, że usuwają właściwy film.
Znacznik zawiera już link umożliwiający użytkownikowi powrót do strony listy filmów.
Podobnie jak na stronie EditFilm , identyfikator wybranego filmu jest przechowywany w ukrytym polu. (Jest on przekazywany do strony w pierwszej kolejności jako wartość ciągu zapytania). Html.ValidationSummary
Istnieje wywołanie, które wyświetli błędy walidacji. W takim przypadku błąd może oznaczać, że żaden identyfikator filmu nie został przekazany do strony lub że identyfikator filmu jest nieprawidłowy. Taka sytuacja może wystąpić, jeśli ktoś uruchomił tę stronę bez uprzedniego wybrania filmu na stronie Filmy .
Podpis przycisku to Delete Movie (Usuń film), a jego atrybut name ma wartość buttonDelete
. Atrybut name
będzie używany w kodzie do identyfikowania przycisku, który przesłał formularz.
Musisz napisać kod do 1) odczytywać szczegóły filmu, gdy strona jest wyświetlana po raz pierwszy i 2) faktycznie usunąć film, gdy użytkownik kliknie przycisk.
Dodawanie kodu do odczytu pojedynczego filmu
W górnej części strony DeleteImage.cshtml dodaj następujący blok kodu:
@{
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 found for that ID.");
}
}
else{
Validation.AddFormError("No movie was found for that ID.");
}
}
}
Ten znacznik jest taki sam jak odpowiedni kod na stronie EditFilm . Pobiera identyfikator filmu z ciągu zapytania i używa identyfikatora do odczytu rekordu z bazy danych. Kod zawiera test weryfikacji (IsInt()
i row != null
), aby upewnić się, że identyfikator filmu przekazywany do strony jest prawidłowy.
Pamiętaj, że ten kod powinien być uruchamiany tylko przy pierwszym uruchomieniu strony. Nie chcesz ponownie odczytywać rekordu filmu z bazy danych, gdy użytkownik kliknie przycisk Usuń film . W związku z tym kod do odczytania filmu znajduje się wewnątrz testu, który mówi if(!IsPost)
— oznacza to, że jeśli żądanie nie jest operacją post (przesyłanie formularza).
Dodawanie kodu w celu usunięcia wybranego filmu
Aby usunąć film po kliknięciu przycisku przez użytkownika, dodaj następujący kod tuż wewnątrz zamykającego nawiasu klamrowego @
bloku:
if(IsPost && !Request["buttonDelete"].IsEmpty()){
movieId = Request.Form["movieId"];
var db = Database.Open("WebPagesMovies");
var deleteCommand = "DELETE FROM Movies WHERE ID = @0";
db.Execute(deleteCommand, movieId);
Response.Redirect("~/Movies");
}
Ten kod jest podobny do kodu służącego do aktualizowania istniejącego rekordu, ale prostszego. Kod zasadniczo uruchamia instrukcję SQL Delete
.
Podobnie jak na stronie EditFilm , kod znajduje się w if(IsPost)
bloku. Tym razem if()
warunek jest nieco bardziej skomplikowany:
if(IsPost && !Request["buttonDelete"].IsEmpty())
Istnieją tu dwa warunki. Pierwszą z nich jest to, że strona jest przesyłana, jak pokazano wcześniej — if(IsPost)
.
Drugi warunek to !Request["buttonDelete"].IsEmpty()
, co oznacza, że żądanie ma obiekt o nazwie buttonDelete
. Co prawda, jest to pośredni sposób testowania, który przycisk przesłał formularz. Jeśli formularz zawiera wiele przycisków przesyłania, w żądaniu pojawia się tylko nazwa klikniętego przycisku. W związku z tym logicznie, jeśli nazwa określonego przycisku pojawia się w żądaniu — lub zgodnie z opisem w kodzie, jeśli ten przycisk nie jest pusty — to jest przycisk, który przesłał formularz.
Operator &&
oznacza "i" (logiczny AND). W związku z tym cały if
warunek to ...
To żądanie jest postem (a nie żądaniem po raz pierwszy)
ORAZ
Przycisk buttonDelete
był przyciskiem, który przesłał formularz.
Ten formularz (w rzeczywistości ta strona) zawiera tylko jeden przycisk, więc dodatkowy test buttonDelete
nie jest technicznie wymagany. Mimo to chcesz wykonać operację, która spowoduje trwałe usunięcie danych. Dlatego chcesz mieć pewność, że wykonujesz operację tylko wtedy, gdy użytkownik jawnie go zażądał. Załóżmy na przykład, że ta strona została później rozwinięta i dodano do niej inne przyciski. Nawet wtedy kod, który usuwa film, zostanie uruchomiony tylko wtedy, gdy buttonDelete
przycisk został kliknięty.
Podobnie jak na stronie EditGroup , identyfikator zostanie wyświetlony z pola ukrytego, a następnie uruchom polecenie SQL. Składnia instrukcji Delete
to:
DELETE FROM table WHERE ID = value
Ważne jest, aby uwzględnić klauzulę WHERE
i identyfikator. Jeśli opuścisz klauzulę WHERE, wszystkie rekordy w tabeli zostaną usunięte. Jak widać, wartość identyfikatora przekazujesz do polecenia SQL przy użyciu symbolu zastępczego.
Testowanie procesu usuwania filmu
Teraz możesz przetestować. Uruchom stronę Filmy i kliknij przycisk Usuń obok filmu. Po wyświetleniu strony DeleteFilm kliknij pozycję Usuń film.
Po kliknięciu przycisku kod usuwa filmy i wraca do listy filmów. Możesz tam wyszukać usunięty film i potwierdzić, że został usunięty.
Następna
W następnym samouczku pokazano, jak nadać całej witrynie wspólny wygląd i układ.
Kompletna lista dla strony filmu (zaktualizowana przy użyciu linków usuwania)
@{
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"),
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
)
)
</div>
<p>
<a href="~/AddMovie">Add a movie</a>
</p>
</body>
</html>
Kompletna lista dla strony DeleteShell
@{
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 found for that ID.");
}
}
else{
Validation.AddFormError("No movie was found for that ID.");
}
}
if(IsPost && !Request["buttonDelete"].IsEmpty()){
movieId = Request.Form["movieId"];
var db = Database.Open("WebPagesMovies");
var deleteCommand = "DELETE FROM Movies WHERE ID = @0";
db.Execute(deleteCommand, movieId);
Response.Redirect("~/Movies");
}
}
<html>
<head>
<title>Delete a Movie</title>
</head>
<body>
<h1>Delete a Movie</h1>
@Html.ValidationSummary()
<p><a href="~/Movies">Return to movie listing</a></p>
<form method="post">
<fieldset>
<legend>Movie Information</legend>
<p><span>Title:</span>
<span>@title</span></p>
<p><span>Genre:</span>
<span>@genre</span></p>
<p><span>Year:</span>
<span>@year</span></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonDelete" value="Delete Movie" /></p>
</fieldset>
<p><a href="~/Movies">Return to movie listing</a></p>
</form>
</body>
</html>
Dodatkowe zasoby
- Wprowadzenie do ASP.NET programowania internetowego przy użyciu składni Razor
- Instrukcja SQL DELETE w witrynie W3Schools