ASP.NET 网页 - 删除数据库数据简介

作者 Tom FitzMacken

本教程介绍如何删除单个数据库条目。 它假定你已通过更新 ASP.NET 网页 中的数据库数据完成了该系列。

学习内容:

  • 如何从记录列表中选择单个记录。
  • 如何从数据库中删除单个记录。
  • 如何检查窗体中单击了特定按钮。

已讨论的功能/技术:

  • 帮助 WebGrid 程序。
  • SQL Delete 命令。
  • 运行 Database.Execute SQL Delete 命令的方法。

所需操作

在上一教程中,你已了解如何更新现有数据库记录。 本教程与此类似,但不会更新记录,而是将其删除。 这些过程大致相同,只是删除操作更简单,因此本教程会很简短。

“电影 ”页中 WebGrid ,你将更新帮助程序,使其在每部电影旁边显示 一个“删除” 链接,以随附前面添加的 “编辑” 链接。

显示每个电影的“删除”链接的“电影”页面

与编辑一样,单击 “删除” 链接时,会转到其他页面,其中电影信息已在窗体中:

显示电影的“删除电影”页面

然后,可以单击该按钮永久删除记录。

首先,将 “删除” 链接添加到 WebGrid 帮助程序。 此链接类似于在上一教程中添加的 “编辑” 链接。

打开 Movies.cshtml 文件。

WebGrid通过添加列来更改页面正文中的标记。 下面是修改后的标记:

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

新列是以下列:

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

配置网格的方式是 ,“编辑” 列在网格中最左侧, “删除” 列最右侧。 (列后面 Year 现在有一个逗号,以防你没有注意到。) 这些链接列的去向没有什么特别之处,你可以轻松地将它们放在一起。 在这种情况下,它们是分开的,使他们更难混在一起。

标记为“编辑”和“详细信息”链接的“电影”页面,以显示它们不相邻

新列显示一个链接 (<a> 元素) ,其文本显示“Delete”。 链接的目标 (其 href 属性) 是最终解析为类似此 URL 的代码,每个 id 电影的值都不同:

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

此链接将调用名为 DeleteMovie 的页面,并向其传递所选电影的 ID。

本教程不会详细介绍此链接的构造方式,因为它与上一教程 (更新 ASP.NET 网页) 中的“编辑数据库数据”链接几乎相同。

创建删除页

现在,可以创建一个页面,该页面将成为网格中 “删除” 链接的目标。

注意

重要 首先选择要删除的记录,然后使用单独的页面和按钮确认该过程的技术对于安全性非常重要。 正如你在前面的教程中读到的,对网站进行 任何形式的 更改都应 始终 使用表单完成,即使用 HTTP POST 操作。 如果只需单击链接 (即使用 GET 操作) 更改网站,则用户可向您的网站发出简单的请求并删除数据。 即使是为网站编制索引的搜索引擎爬网程序,也可能无意中仅通过以下链接删除数据。

当你的应用允许用户更改记录时,你必须将记录呈现给用户进行编辑。 但是,删除记录时可能会跳过此步骤。 不过,不要跳过此步骤。 (用户查看记录并确认他们正在删除他们想要的记录也很有帮助。)

在后续教程集中,你将了解如何添加登录功能,以便用户必须在删除记录之前登录。

创建名为 DeleteMovie.cshtml 的页面,并将文件中的内容替换为以下标记:

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

此标记类似于 EditMovie 页面,不同之处在于,标记包含<span>元素,而不是使用文本框 (<input type="text">) 。 此处没有可编辑的内容。 只需显示电影详细信息,以便用户能够确保删除正确的电影。

标记已包含允许用户返回到电影列表页面的链接。

EditMovie 页中一样,所选电影的 ID 存储在隐藏字段中。 (它首先作为查询字符串值传递到页面。) 有一个 Html.ValidationSummary 调用将显示验证错误。 在这种情况下,错误可能是没有将电影 ID 传递到页面,或者电影 ID 无效。 如果有人在没有先在“ 电影 ”页中选择电影的情况下运行此页面,则可能会出现这种情况。

按钮描述文字为“删除影片”,其 name 属性设置为 buttonDelete。 特性 name 将在代码中用于标识提交表单的按钮。

你必须在首次显示页面时将代码写入 1 个,) 读取电影详细信息,当用户单击该按钮时,2) 实际删除电影。

添加代码以阅读单个电影

DeleteMovie.cshtml 页的顶部,添加以下代码块:

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

此标记与 EditMovie 页中的相应代码相同。 它从查询字符串中获取电影 ID,并使用 ID 从数据库读取记录。 该代码包括验证测试 (IsInt()row != null) ,以确保传递给页面的电影 ID 有效。

请记住,此代码应仅在页面首次运行时运行。 用户单击“删除影片”按钮时,不希望从数据库中重新读取 电影 记录。 因此,用于阅读电影的代码位于一个测试 if(!IsPost) 中,即 ,如果请求不是 post 操作, (表单提交)

添加代码以删除所选电影

若要在用户单击按钮时删除电影,请在块的 @ 右大括号内添加以下代码:

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

此代码类似于更新现有记录的代码,但更简单。 代码基本上运行 SQL Delete 语句。

EditMovie 页中一样,代码位于块 if(IsPost) 中。 这一次, if() 条件稍微复杂一点:

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

此处有两个条件。 第一个是正在提交页面,如前所述 - if(IsPost)

第二个条件是 !Request["buttonDelete"].IsEmpty(),这意味着请求有一个名为 的对象 buttonDelete。 不可否认,这是一种间接测试哪个按钮提交了表单。 如果窗体包含多个提交按钮,则请求中仅显示单击的按钮的名称。 因此,从逻辑上讲,如果特定按钮的名称出现在请求中,或者如代码中所述,如果该按钮不为空,则为提交表单的按钮。

运算符 && 表示“和” (逻辑 AND) 。 因此,整个 if 条件为 ...

此请求是发布 (不是首次请求)

AND

buttonDelete按钮是提交表单的按钮。

事实上,此窗体 (,此页面) 只包含一个按钮,因此在技术上不需要对 buttonDelete 进行额外的测试。 不过,你将执行将永久删除数据的操作。 因此,你希望尽可能确保仅在用户显式请求该操作时才执行该操作。 例如,假设你稍后展开了此页面,并添加了其他按钮。 即便如此,仅当单击按钮时 buttonDelete ,删除电影的代码才会运行。

在 EditMovie 页中一样,可以从隐藏字段获取 ID,然后运行 SQL 命令。 语句的 Delete 语法为:

DELETE FROM table WHERE ID = value

必须包含 WHERE 子句和 ID。 如果省略 WHERE 子句, 则表中的所有记录都将被删除。 如前所述,使用占位符将 ID 值传递给 SQL 命令。

测试电影删除过程

现在可以测试了。 运行 “电影 ”页,然后单击电影旁边的“ 删除 ”。 出现 “DeleteMovie ”页时,单击“ 删除电影”。

突出显示“删除影片”按钮的“删除影片”页

单击该按钮时,代码会删除电影并返回到电影列表。 你可以在那里搜索已删除的电影,并确认它已被删除。

即将推出下一步

下一教程介绍如何为站点上的所有页面提供通用的外观和布局。

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

DeleteMovie 页面的完整列表

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

其他资源