ASP.NET Web ページの概要 - データベース データの削除

Tom FitzMacken

このチュートリアルでは、個々のデータベース エントリを削除する方法について説明します。 ASP.NET Web ページのデータベース データの更新を通じてシリーズを完了していることを前提としています。

ここでは、次の内容について学習します。

  • レコードの一覧から個々のレコードを選択する方法。
  • データベースから 1 つのレコードを削除する方法。
  • 特定のボタンがフォーム内でクリックされたことをチェックする方法。

説明されている機能/テクノロジ:

  • WebGridヘルパー。
  • SQL Delete コマンド。
  • Database.Execute SQL Delete コマンドを実行するメソッド。

作成するアプリケーション:

前のチュートリアルでは、既存のデータベース レコードを更新する方法について説明しました。 このチュートリアルは似ていますが、レコードを更新する代わりに削除します。 プロセスは、削除が簡単であることを除いて、ほとんど同じですので、このチュートリアルは短くなります。

[ムービー] ページで、ヘルパーをWebGrid更新して、前に追加した [編集] リンクに付随する各ムービーの横に [削除] リンクが表示されるようにします。

各ムービーの [削除] リンクが表示されている [ムービー] ページ

編集と同様に、[ 削除 ] リンクをクリックすると、別のページに移動します。ここで、ムービー情報は既にフォームに含まれています。

ムービーが表示された [ムービーの削除] ページ

その後、ボタンをクリックしてレコードを完全に削除できます。

最初に、ヘルパーに Delete リンクを 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>)

グリッドの構成方法として、[ 編集] 列はグリッドの左端に、 Delete 列は右端に表示されます。 (気付かなかった場合に備えて、列の後 Year にコンマがあります)。これらのリンク列の場所に関して特別なものは何もありません。また、それらを互いに簡単に配置できます。 この場合、混同を難しくするために分離されています。

[編集] リンクと [詳細] リンクが付いた [ムービー] ページで、互いに隣り合っていないことを示すマークが付いています

新しい列には、テキストに "Delete" と表示されるリンク (<a> 要素) が表示されます。 リンクのターゲット (その href 属性) は、最終的に次のような URL に解決され、ムービーごとに値が id 異なるコードです。

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

このリンクは DeleteMovie という名前のページを呼び出し、選択したムービーの ID を渡します。

このチュートリアルでは、このリンクの作成方法については詳しく説明しません。これは、前のチュートリアル (ASP.NET Web ページでのデータベース データの更新) の [編集] リンクとほぼ同じであるためです。

削除ページの作成

これで、グリッドの [削除 ] リンクのターゲットとなるページを作成できます。

Note

大事な 最初に削除するレコードを選択し、別のページとボタンを使用してプロセスを確認する手法は、セキュリティにとって非常に重要です。 前のチュートリアルで読んだように、Web サイトに 何らかの 変更を加えるには、 常に フォーム (つまり 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 ページに似ていますが、テキスト ボックス (<input type="text">) を使用する代わりに、マークアップに要素が含まれる <span> 点が除きます。 ここには何も編集する必要はありません。 ユーザーが適切なムービーを削除していることを確認できるように、映画の詳細を表示する必要があります。

マークアップには、ユーザーが映画の一覧ページに戻ることができるリンクが既に含まれています。

EditMovie ページと同様に、選択したムービーの ID は非表示フィールドに格納されます。 (最初にクエリ文字列値としてページに渡されます)。検証エラーを Html.ValidationSummary 表示する呼び出しがあります。 この場合、ムービー ID がページに渡されなかったか、ムービー ID が無効である可能性があります。 この状況は、[ 映画] ページで最初にムービーを選択せずにこのページを実行した場合に発生する可能性があります。

ボタン キャプションは [ムービーの削除] で、その name 属性は にbuttonDelete設定されます。 属性は name 、フォームを送信したボタンを識別するためにコードで使用されます。

1) ページが最初に表示されたときにムービーの詳細を読み取り、2) ユーザーがボタンをクリックしたときにムービーを実際に削除するコードを記述する必要があります。

1 つのムービーを読み取るコードの追加

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 を使用してデータベースからレコードを読み取ります。 このコードには、ページに渡されるムービー ID が有効であることを確認するための検証テスト (IsInt()row != null) が含まれています。

このコードは、ページを初めて実行するときにのみ実行する必要があります。 ユーザーが [ムービーの 削除 ] ボタンをクリックしたときに、データベースからムービー レコードを再読み取りする必要はありません。 そのため、ムービーを読み取るコードは、 というテスト if(!IsPost) 内にあります。つまり、 要求がポスト操作 (フォーム送信) でない場合です。

選択したムービーを削除するコードの追加

ユーザーがボタンをクリックしたときにムービーを削除するには、ブロックの右中かっこの内側に次のコードを @ 追加します。

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

ここには 2 つの条件があります。 1 つ目は、前に見たように、ページが送信されていることです。 if(IsPost)

2 番目の条件は です !Request["buttonDelete"].IsEmpty()。これは、要求に という名前 buttonDeleteのオブジェクトがあることを意味します。 確かに、これは、フォームを送信したボタンをテストする間接的な方法です。 フォームに複数の送信ボタンが含まれている場合は、クリックされたボタンの名前のみが要求に表示されます。 したがって、論理的には、特定のボタンの名前が要求に表示される場合、またはコードに記載されているように、そのボタンが空でない場合は、フォームを送信したボタンです。

演算子は && "and" (論理 AND) を意味します。 したがって、条件全体 if は ... です。

この要求は投稿です (初回要求ではありません)

AND

次の値を使用buttonDeleteボタンは、フォームを送信したボタンです。

このフォーム (実際、このページ) にはボタンが 1 つだけ含まれているため、 の追加テスト buttonDelete は技術的には必要ありません。 それでも、データを完全に削除する操作を実行します。 そのため、ユーザーが明示的に要求した場合にのみ、操作を実行していることを可能な限り確認する必要があります。 たとえば、後でこのページを展開し、そのページに他のボタンを追加したとします。 それでも、ムービーを削除するコードは、ボタンが buttonDelete クリックされた場合にのみ実行されます。

EditMovie ページと同様に、非表示フィールドから ID を取得し、SQL コマンドを実行します。 ステートメントの Delete 構文は次のとおりです。

DELETE FROM table WHERE ID = value

句と ID を WHERE 含める必要があります。 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>

その他のリソース