Введение веб-страницы ASP.NET-удаление данных базы данныхIntroducing ASP.NET Web Pages - Deleting Database Data

от Tom фитзмаккенby Tom FitzMacken

В этом учебнике показано, как удалить отдельную запись базы данных.This tutorial shows you how to delete an individual database entry. Предполагается, что вы выполнили цикл по обновлению данных базы данных в веб-страницы ASP.NET.It assumes you have completed the series through Updating Database Data in ASP.NET Web Pages.

Из этого руководства вы узнаете, как выполнять такие задачи:What you'll learn:

  • Выбор отдельной записи из списка записей.How to select an individual record from a listing of records.
  • Удаление одной записи из базы данных.How to delete a single record from a database.
  • Как проверить, была ли нажата определенная кнопка в форме.How to check that a specific button was clicked in a form.

Обсуждаемые функции и технологии:Features/technologies discussed:

  • Вспомогательный метод WebGrid.The WebGrid helper.
  • Команда SQL Delete.The SQL Delete command.
  • Метод Database.Execute для выполнения команды SQL Delete.The Database.Execute method to run a SQL Delete command.

Что вы создадитеWhat You'll Build

В предыдущем руководстве вы узнали, как обновить существующую запись базы данных.In the previous tutorial, you learned how to update an existing database record. Этот учебник аналогичен, но вместо обновления записи вы удалите его.This tutorial is similar, except that instead of updating the record, you'll delete it. Процессы во многом одинаковы, за исключением того, что удаление упрощается, поэтому этот учебник будет небольшим.The processes are much the same, except that deleting is simpler, so this tutorial will be short.

На странице фильмов вы обновите вспомогательную функцию WebGrid, чтобы она отображала ссылку Delete (удалить ) рядом с каждым фильмом, сопровождающую ссылку на изменение , добавленную ранее.In the Movies page, you'll update the WebGrid helper so that it displays a Delete link next to each movie to accompany the Edit link you added earlier.

Страница фильмов, на которой показана ссылка для удаления каждого фильма

Как и при редактировании, при щелчке ссылки Удалить выполняется переход на другую страницу, где сведения о фильме уже находятся в форме:As with editing, when you click the Delete link, it takes you to a different page, where the movie information is already in a form:

Удаление страницы фильма с отображаемым фильмом

Затем можно нажать кнопку, чтобы удалить запись без возможности восстановления.You can then click the button to delete the record permanently.

Начнем с добавления ссылки Delete в вспомогательную функцию WebGrid.You'll start by adding a Delete link to the WebGrid helper. Эта ссылка похожа на ссылку редактирования , добавленную в предыдущем руководстве.This link is similar to the Edit link you added in a previous tutorial.

Откройте файл movies. cshtml .Open the Movies.cshtml file.

Измените WebGrid разметку в тексте страницы, добавив столбец.Change the WebGrid markup in the body of the page by adding a column. Измененная разметка:Here's the modified 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"),
grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)
    )
)

Новый столбец является следующим:The new column is this one:

grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)

Способ настройки сетки, столбец « Правка » является крайним левым в сетке, а столбец « Удаление » — крайний правый.The way the grid is configured, the Edit column is leftmost in the grid and the Delete column is rightmost. (В случае, если вы не заметите, есть запятая после Year столбца.) Нет ничего особенного, о том, где находятся эти ссылочные столбцы, и можно легко разместить их рядом друг с другом.(There's a comma after the Year column now, in case you didn't notice that.) There's nothing special about where these link columns go, and you could as easily put them next to each other. В этом случае они разделяются, чтобы их было сложнее приступить к изприятию.In this case, they're separate to make them harder to get mixed up.

Страница "фильмы" с ссылками "Изменить" и "подробности", помеченными, чтобы показывать, что они не находятся рядом

В новом столбце отображается ссылка (<a> элемент), текст которой говорит «DELETE».The new column shows a link (<a> element) whose text says "Delete". Целевой объект ссылки (его атрибут href) — это код, который, в конечном итоге, разрешается в нечто вроде этого URL-адреса, и id значение для каждого фильма отличается.The target of the link (its href attribute) is code that ultimately resolves to something like this URL, with the id value different for each movie:

http://localhost:43097/DeleteMovie?id=7

Эта ссылка приведет к вызову страницы с именем делетемовие и передаче ей идентификатора выбранного фильма.This link will invoke a page named DeleteMovie and pass it the ID of the movie you've selected.

В этом учебнике не будет подробно рассмотрено, как создается эта ссылка, так как она почти идентична ссылке Edit из предыдущего руководства (Обновление данных базы данных в веб-страницы ASP.NET).This tutorial won't go into detail about how this link is constructed, because it's almost identical to the Edit link from the previous tutorial (Updating Database Data in ASP.NET Web Pages).

Создание страницы удаленияCreating the Delete Page

Теперь можно создать страницу, которая будет целевым объектом для ссылки Delete в сетке.Now you can create the page that will be the target for the Delete link in the grid.

Note

Важно! Метод сначала выбирает удаляемую запись, а затем использует отдельную страницу и кнопку для подтверждения того, что процесс чрезвычайно важен для обеспечения безопасности.Important The technique of first selecting a record to delete and then using a separate page and button to confirm the process is extremely important for security. Как вы прочитали в предыдущих учебных курсах, внесение изменений на веб-сайт всегда должно выполняться с помощью формы — то есть с помощью операции HTTP POST.As you've read in previous tutorials, making any sort of change to your website should always be done using a form — that is, using an HTTP POST operation. Если вы сделали возможным изменение сайта просто щелкнув ссылку (то есть с помощью операции GET), пользователи смогут выполнять простые запросы к сайту и удалять данные.If you made it possible to change the site just by clicking a link (that is, using a GET operation), people could make simple requests to your site and delete your data. Даже модуль поиска, который индексирует ваш сайт, может случайно удалить данные только по следующим ссылкам.Even a search-engine crawler that's indexing your site could inadvertently delete data just by following links.

Когда приложение позволяет пользователям изменять запись, в любом случае необходимо предоставить пользователю запись для редактирования.When your app lets people change a record, you have to present the record to the user for editing anyway. Но вы, возможно, пропустите этот шаг, чтобы удалить запись.But you might be tempted to skip this step for deleting a record. Но не пропустите этот шаг.Don't skip that step, though. (Кроме того, пользователям рекомендуется просматривать записи и подтверждать, что они удаляют записи, которые они предполагали.)(It's also helpful for users to see the record and confirm that they're deleting the record that they intended.)

В последующем наборе руководств вы узнаете, как добавить функции входа в систему, чтобы пользователь мог выполнить вход перед удалением записи.In a subsequent tutorial set, you'll see how to add login functionality so a user would have to log in before deleting a record.

Создайте страницу с именем делетемовие. cshtml и замените содержимое файла следующей разметкой:Create a page named DeleteMovie.cshtml and replace what's in the file with the following markup:

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

Эта разметка похожа на страницы едитмовие , за исключением того, что вместо использования текстовых полей (<input type="text">) разметка включает <span> элементы.This markup is like the EditMovie pages, except that instead of using text boxes (<input type="text">), the markup includes <span> elements. Здесь нет ничего редактировать.There's nothing here to edit. Все, что нужно сделать, — отобразить сведения о фильме, чтобы пользователи могли убедиться, что они удаляют нужный фильм.All you have to do is display the movie details so that users can make sure that they're deleting the right movie.

Разметка уже содержит ссылку, которая позволяет пользователю вернуться на страницу со списком фильмов.The markup already contains a link that lets the user return to the movie listing page.

Как и на странице едитмовие , идентификатор выбранного фильма хранится в скрытом поле.As in the EditMovie page, the ID of the selected movie is stored in a hidden field. (Он передается на страницу в первом месте как значение строки запроса). Есть Html.ValidationSummary вызов, который будет отображать ошибки проверки.(It's passed into the page in the first place as a query string value.) There's an Html.ValidationSummary call that will display validation errors. В этом случае ошибка может быть вызвана тем, что на страницу не был передан идентификатор фильма или что идентификатор фильма недопустим.In this case, the error might be that no movie ID was passed to the page or that the movie ID is invalid. Такая ситуация может возникнуть, если кто-то запустил эту страницу без предварительного выбора фильма на странице фильмов .This situation could occur if someone ran this page without first selecting a movie in the Movies page.

Заголовок кнопки — удалить фильм, а его атрибут name имеет значение buttonDelete.The button caption is Delete Movie, and its name attribute is set to buttonDelete. Атрибут name будет использоваться в коде для распознавания кнопки, которая отправила форму.The name attribute will be used in the code to identify the button that submitted the form.

Вам потребуется написать код в 1) прочитать сведения о фильме при первом отображении страницы и 2) удалить фильм, когда пользователь нажмет кнопку.You'll have to write code to 1) read the movie details when the page is first displayed and 2) actually delete the movie when the user clicks the button.

Добавление кода для чтения одного фильмаAdding Code to Read a Single Movie

В верхней части страницы делетемовие. cshtml добавьте следующий блок кода:At the top of the DeleteMovie.cshtml page, add the following code block:

@{
    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.");
        }
    }
}

Эта разметка аналогична соответствующему коду на странице едитмовие .This markup is the same as the corresponding code in the EditMovie page. Он получает идентификатор фильма из строки запроса и использует идентификатор для чтения записи из базы данных.It gets the movie ID out of the query string and uses the ID to read a record from the database. Код включает проверочный тест (IsInt() и row != null), чтобы убедиться, что идентификатор фильма, передаваемый на страницу, является допустимым.The code includes the validation test (IsInt() and row != null) to make sure that the movie ID being passed to the page is valid.

Помните, что этот код должен выполняться только при первом запуске страницы.Remember that this code should only run the first time the page runs. Вы не хотите повторно считывать запись фильма из базы данных, когда пользователь нажимает кнопку удалить фильм .You don't want to re-read the movie record from the database when the user clicks the Delete Movie button. Таким образом, код для чтения фильма находится внутри теста, который говорит if(!IsPost) — то есть, Если запрос не является операцией POST (отправка формы) .Therefore, code to read the movie is inside a test that says if(!IsPost) — that is, if the request is not a post operation (form submission).

Добавление кода для удаления выбранного фильмаAdding Code to Delete the Selected Movie

Чтобы удалить фильм при нажатии кнопки, добавьте следующий код непосредственно в закрывающую фигурную скобку блока @:To delete the movie when the user clicks the button, add the following code just inside the closing brace of the @ block:

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

Этот код похож на код для обновления существующей записи, но проще.This code is similar to the code for updating an existing record, but simpler. Код, по сути, выполняет инструкцию SQL Delete.The code basically runs a SQL Delete statement.

Как и на странице едитмовие , код находится в блоке if(IsPost).As in the EditMovie page, the code is in an if(IsPost) block. На этот раз if() условие немного сложнее:This time, the if() condition is a little more complicated:

if(IsPost && !Request["buttonDelete"].IsEmpty())

Здесь есть два условия.There are two conditions here. Первый заключается в том, что страница отправляется, как показано выше — if(IsPost).The first is that the page is being submitted, as you've seen before — if(IsPost).

Второе условие — !Request["buttonDelete"].IsEmpty(), то есть запрос содержит объект с именем buttonDelete.The second condition is !Request["buttonDelete"].IsEmpty(), meaning that the request has an object named buttonDelete. Разумеется, это косвенный способ проверки того, какая кнопка отправила форму.Admittedly, it's an indirect way of testing which button submitted the form. Если форма содержит несколько кнопок отправки, в запросе отображается только имя кнопки, которая была нажата.If a form contains multiple submit buttons, only the name of the button that was clicked appears in the request. Таким образом, логически, если имя определенной кнопки появляется в запросе — или как указано в коде, если эта кнопка не пуста — это кнопка, которая отправляла форму.Therefore, logically, if the name of a particular button appears in the request — or as stated in the code, if that button isn't empty — that's the button that submitted the form.

Оператор && означает "and" (логическое и).The && operator means "and" (logical AND). Таким образом, все if условие имеет значение...Therefore the entire if condition is ...

Этот запрос является сообщением POST (не запросом в первый раз)This request is a post (not a first-time request)

ANDAND

Кнопка buttonDeleteбыла отправлена в форму.The buttonDeletebutton was the button that submitted the form.

Эта форма (на самом деле, эта страница) содержит только одну кнопку, поэтому дополнительный тест buttonDelete технически не является обязательным.This form (in fact, this page) contains only one button, so the additional test for buttonDelete is technically not required. Тем не менее вы собираетесь выполнить операцию, которая будет окончательно удалять данные.Still, you're about to perform an operation that will permanently remove data. Так что вы должны быть уверены, что операция выполняется только в том случае, если пользователь явно запросил ее.So you want to be as sure as possible that you're performing the operation only when the user has explicitly requested it. Например, предположим, что вы развернули эту страницу позже и добавили в нее другие кнопки.For example, suppose that you expanded this page later and added other buttons to it. Даже после этого код, который удаляет фильм, будет выполняться только в том случае, если была нажата кнопка buttonDelete.Even then, the code that deletes the movie will run only if the buttonDelete button was clicked.

Как и на странице едитмовие , вы получаете идентификатор из скрытого поля, а затем выполняете команду SQL.As in the EditMovie page, you get the ID from the hidden field and then run the SQL command. Синтаксис инструкции Delete:The syntax for the Delete statement is:

DELETE FROM table WHERE ID = value

Крайне важно включать предложение WHERE и идентификатор.It's vital to include the WHERE clause and the ID. Если оставить предложение WHERE, все записи в таблице будут удалены.If you leave out the WHERE clause, all the records in the table will be deleted. Как вы видите, значение идентификатора передается команде SQL с помощью заполнителя.As you have seen, you pass the ID value to the SQL command by using a placeholder.

Тестирование процесса удаления фильмаTesting the Movie Delete Process

Теперь можно протестировать.Now you can test. Запустите страницу фильмов и щелкните Удалить рядом с фильмом.Run the Movies page, and click Delete next to a movie. Когда появится страница делетемовие , щелкните удалить фильм.When the DeleteMovie page appears, click Delete Movie.

Удаление страницы фильма с выделенной кнопкой "удалить фильм"

При нажатии кнопки код удаляет фильмы и возвращает их в список фильмов.When you click the button, the code deletes the movies and returns to the movie listing. Там можно найти удаленный фильм и убедиться, что он был удален.There you can search for the deleted movie and confirm that it's been deleted.

ДалееComing Up Next

В следующем учебнике показано, как дать всем страницам на сайте общий вид и макет.The next tutorial shows you how to give all the pages on your site a common look and layout.

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

Полный список для страницы ДелетемовиеComplete Listing for DeleteMovie Page

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

Дополнительные ресурсыAdditional Resources