次の方法で共有


ASP.NET Web ページ (Razor) サイトでのデータベースの操作の概要

Tom FitzMacken

この記事では、Microsoft WebMatrix ツールを使用して、ASP.NET Web ページ (Razor) Web サイトにデータベースを作成する方法と、データを表示、追加、編集、削除できるページを作成する方法について説明します。

学習内容:

  • データベースを作成する方法
  • データベースに接続する方法
  • Web ページにデータを表示する方法。
  • データベース レコードを挿入、更新、削除する方法。

この記事で紹介する機能は次のとおりです。

  • Microsoft SQL Server Compact Edition データベースの操作。
  • SQL クエリの操作。
  • Database クラスです。

チュートリアルで使用するソフトウェアのバージョン

  • ASP.NET Web ページ (Razor) 2
  • WebMatrix 2

このチュートリアルは、WebMatrix 3 でも動作します。 ASP.NET Web ページ 3 と Visual Studio 2013 (または Visual Studio Express 2013 for Web) を使用できます。ただし、ユーザー インターフェイスは異なります。

データベースの概要

よくあるアドレス帳を想像してみてください。 アドレス帳の各エントリ、つまり 1 人の人について、名、姓、住所、電子メール アドレス、電話番号などのいくつかの情報があります。

このようなデータを表現する一般的な方法は、行と列を持つテーブルです。 データベースの用語では、各行はレコードと呼ばれることがよくあります。 各列 (フィールドとも呼ばれます) には、名、姓などのデータの種類別の値が格納されます。

ID FirstName 住所 電子メール 電話
1 Jim Abrus 210 100th St SE Orcas WA 98031 jim@contoso.com 555 0100
2 Terry Adams 1234 Main St. Seattle WA 99011 terry@cohowinery.com 555 0101

ほとんどのデータベース テーブルでは、顧客番号やアカウント番号など、テーブルに一意の識別子を含む列が必要です。これはテーブルの主キーと呼ばれ、テーブル内の各行を識別するために使用します。 この例では、ID 列がアドレス帳の主キーです。

データベースに関するこの基本を理解することで、単純なデータベースを作成し、データの追加、変更、削除などの操作を実行する方法を学習できます。

ヒント

リレーショナル データベース

データはテキスト ファイルやスプレッドシートなど、さまざまな方法で格納できます。 ただし、ほとんどのビジネス用途では、データはリレーショナル データベースに格納されます。

この記事では、データベースについては詳しく説明していません。 ただし、それらについて少し理解しておくと、役に立つ場合があります。 リレーショナル データベースでは、情報は論理的に別々のテーブルに分割されます。 たとえば、学校のデータベースには、生徒とクラス オファリング用の個別のテーブルが格納されていると考えられます。 データベース ソフトウェア (SQL Server など) では、テーブル間のリレーションシップを動的に確立できる高機能なコマンドがサポートされています。 たとえば、リレーショナル データベースを使用して、スケジュールを作成するために生徒とクラスの間に論理的なリレーションシップを確立できます。 データを別のテーブルに格納することで、テーブル構造の複雑さが軽減され、テーブル内に冗長なデータを保持する必要性が低減します。

データベースの作成

この手順では、WebMatrix に含まれている SQL Server Compact Database デザイン ツールを使用して、SmallBakery という名前のデータベースを作成する方法を示します。 データベースはコードを使用して作成できますが、WebMatrix などのデザイン ツールを使用してデータベースとデータベース テーブルを作成する方が一般的です。

  1. WebMatrix を起動し、[クイック スタート] ページで [Site From Template]\(テンプレートからのサイト\) を選択します。

  2. [空のサイト] を選択し、[サイト名] ボックスに「SmallBakery」と入力し、[OK] をクリックします。 サイトが作成され、WebMatrix に表示されます。

  3. 左側のウィンドウで、[データベース]ワークスペースをクリックします。

  4. リボンの [新しいデータベース] をクリックします。 サイトと同じ名前の空のデータベースが作成されます。

  5. 左側のウィンドウで、SmallBakery.sdf ノードを展開し、[テーブル] をクリックします。

  6. リボンの [新しいテーブル] をクリックします。 WebMatrix でテーブル デザイナーが開きます。

    [Screenshot shows Web Matrix opening the table designer.]

  7. [名前] 列をクリックし、「Id」と入力します。

  8. [データ型] 列で、[int] を選択します。

  9. [主キーか] オプションと [ID?] オプションを [はい] に設定します。

    名前が示すように、[主キーか] は、これがテーブルの主キーであることをデータベースに伝えます。 [ID?] は、新しいレコードごとに ID 番号を自動的に作成し、1 から始まる連続する次の番号を割り当てるように、データベースに指示します。

  10. 次の行をクリックします。 エディターが新しい列定義を開始します。

  11. [名前] の値に「Name」と入力します。

  12. [データ型] で [nvarchar] を選択し、長さを 50 に設定します。 nvarcharvar 部分は、この列のデータが、レコードごとにサイズが異なる可能性がある文字列であることをデータベースに伝えます。 (n プレフィックスは national を表します。これは、このフィールドがアルファベットまたは書き込みシステムを表す文字データを保持できることを示します。つまり、このフィールドは Unicode データを保持します)。

  13. [Null を許容] オプションを [いいえ] に設定します。 これにより、[Name] 列が空白のままにならないことが強制的に適用されます。

  14. この同じプロセスを使用して、Description という名前の列を作成します。 [データ型] を "nvarchar" に設定し、長さを 50 に設定し、[Null を許容] を false に設定します。

  15. Price という名前の列を作成します。 [データ型] を "money" に設定し、[Null を許容] を false に設定します。

  16. 上部のボックスで、テーブルに "Product" という名前を付けます。

    完了すると、定義は次のようになります。

    [Screenshot shows what the definition will look like when finished.]

  17. Ctrl + S キーを押して、テーブルを保存します。

データのデータベースへの追加

これで、サンプル データをデータベースに追加できるようになりました。これらのデータは、この記事の後半で使用します。

  1. 左側のウィンドウで、SmallBakery.sdf ノードを展開し、[テーブル] をクリックします。

  2. Product テーブルを右クリックし、[データ] をクリックします。

  3. 編集ウィンドウで、次のレコードを入力します。

    名前 説明 価格
    パン 毎日焼きたて。 2.99
    いちごショートケーキ 自家菜園のオーガニックいちごを使用。 9.99
    アップル パイ お母さんの手作りパイに次ぐおいしさ。 12.99
    ピーカン パイ ピーカン好きに一押し。 10.99
    レモン パイ 世界最高のレモンを使用。 11.99
    カップケーキ お子様と童心に返った大人の皆様に。 7.99

    [Id] 列には何も入力する必要はありません。 [Id] 列を作成するときに、その Is Identity プロパティを true に設定すると、この列は自動的に入力されます。

    データの入力が完了すると、テーブル デザイナーは次のようになります。

    [Screenshot shows what the table designer will look like when the data is finished being entered.]

  4. データベース データを含むタブを閉じます。

データベースからのデータの表示

データを含むデータベースを取得したら、ASP.NET Web ページにデータを表示できます。 表示するテーブル行を選択するには、データベースに渡すコマンドである SQL ステートメントを使用します。

  1. 左側のウィンドウで、[ファイル] ワークスペースをクリックします。

  2. Web サイトのルートで、ListProducts.cshtml という名前の新しい CSHTML ページを作成します。

  3. 既存のマークアップを次に置き換えます。

    @{
        var db = Database.Open("SmallBakery");
        var selectQueryString = "SELECT * FROM Product ORDER BY Name";
     }
    <!DOCTYPE html>
    <html>
     <head>
       <title>Small Bakery Products</title>
       <style>
           table, th, td {
             border: solid 1px #bbbbbb;
             border-collapse: collapse;
             padding: 2px;
           }
        </style>
     </head>
     <body>
       <h1>Small Bakery Products</h1>
       <table>
           <thead>
               <tr>
                   <th>Id</th>
                   <th>Product</th>
                   <th>Description</th>
           <th>Price</th>
               </tr>
           </thead>
           <tbody>
               @foreach(var row in db.Query(selectQueryString)){
                <tr>
                   <td>@row.Id</td>
                       <td>@row.Name</td>
                       <td>@row.Description</td>
                       <td>@row.Price</td>
                </tr>
               }
           </tbody>
       </table>
     </body>
    </html>
    

    最初のコード ブロックで、先ほど作成した SmallBakery.sdf ファイル (データベース) を開きます。 Database.Open メソッドは、.sdf ファイルが Web サイトの App_Data フォルダーにあることを前提としています。 (.sdf 拡張子を指定する必要がないことに注目してください。指定した場合、Open メソッドは機能しません)。

    Note

    App_Data フォルダーは、データ ファイルの格納に使用される ASP.NET 内の特別なフォルダーです。 詳細については、この記事で後述する「データベースに接続する」を参照してください。

    その後、次の SQL Select ステートメントを使用して、データベースに対してクエリを実行する要求を行います。

    SELECT * FROM Product ORDER BY Name
    

    ステートメントで、Product クエリを実行するテーブルを特定します。 * 文字は、クエリがテーブルからすべての列を返すように指定します。 (一部の列のみを表示する場合は、コンマで区切って列を個別に一覧表示することもできます)。Order By 句は、データの並べ替え方法を示します。ここでは、[Name] 列を使用して示します。 つまり、各行の [Name] 列の値に基づいて、データがアルファベット順に並べ替えられます。

    ページの本文に、マークアップによって、データの表示に使用される HTML テーブルが作成されます。 <tbody> 要素内で foreach ループを使用して、クエリによって返される各データ行を個別に取得します。 データ行ごとに、HTML テーブル行 (<tr> 要素) を作成します。 次に、各列の HTML テーブル セル (<td> 要素) を作成します。 ループを実行するたびに、データベースから次に使用可能な行が row 変数内に格納されます (これは、foreach ステートメント内で設定します)。 行から個々の列を取得するには、row.Name または row.Description、または任意の列の名前を使用できます。

  4. ブラウザーでページを実行します。 (実行する前に、ファイル ワークスペースでページが選択されていることを確認してください。)このページには、次のような一覧が表示されます。

    [Screenshot shows the list the page will display in the browser.]

ヒント

構造化照会言語 (SQL)

SQL は、データベース内のデータを管理するためにほとんどのリレーショナル データベースで使用される言語です。 これには、データを取得して更新できるコマンドと、データベース テーブルの作成、変更、管理を行うコマンドが含まれています。 SQL はプログラミング言語 (WebMatrix で使用している言語など) とは異なります。SQL では、データベースに必要な情報を伝えるのが開発者の仕事であり、データの取得方法やタスクの実行方法を決めるのはデータベースの仕事であるという考え方です。 SQL コマンドとその実行例をいくつか次に示します。

SELECT Id, Name, Price FROM Product WHERE Price > 10.00 ORDER BY Name

これにより、[Price] 列の値が 10 を超える場合、[Product] テーブルのレコードから [Id][Name][Price] の各列がフェッチされ、[Name] 列の値に基づいて結果がアルファベット順に返されます。 このコマンドは、条件を満たすレコードを含む結果セットを返します。一致するレコードがない場合は空のセットを返します。

INSERT INTO Product (Name, Description, Price) VALUES ("Croissant", "A flaky delight", 1.99)

これにより、Product テーブルに新しいレコードが挿入され、[Name] 列が "Croissant" に設定され、[Description] 列が "A flaky delight" に設定され、価格が 1.99 に設定されます。

DELETE FROM Product WHERE ExpirationDate < "01/01/2008"

このコマンドは、Product テーブル内の有効期限列が 2008 年 1 月 1 日より前のレコードを削除します。 (これは、Product テーブルにこのような列があることを前提としています)。日付は MM/DD/YYYY 形式で入力しますが、ご利用のロケールに使用される形式で入力する必要があります。

Insert Into コマンドと Delete コマンドは結果セットを返しません。 代わりに、コマンドの影響を受けたレコードの数を示す数値を返します。

これらの操作の一部 (レコードの挿入や削除など) では、操作を要求するプロセスにデータベース内の適切なアクセス許可が必要です。 このため、実稼働用データベースでは、データベースに接続するときにユーザー名とパスワードを指定する必要がよくあります。

SQL コマンドは多数ありますが、これらはすべて次のようなパターンに従います。 SQL コマンドを使用すると、データベース テーブルの作成、テーブル内のレコード数のカウント、価格の計算など、多様な操作を実行できます。

データベースへのデータの挿入

このセクションでは、ユーザーが Product データベース テーブルに新しい製品を追加できるページを作成する方法について説明します。 新しい製品レコードが挿入されると、前のセクションで作成した ListProducts.cshtml ページを使用して、更新されたテーブルがページに表示されます。

このページには、ユーザーが入力したデータがデータベースに対して有効であることを確認するための検証が含まれています。 たとえば、ページ内のコードでは、すべての必須列に対して値が入力されていることを確認します。

  1. Web サイトで、InsertProducts.cshtml という名前の新しい CSHTML ファイルを作成します。

  2. 既存のマークアップを次に置き換えます。

    @{
        Validation.RequireField("Name", "Product name is required.");
        Validation.RequireField("Description", "Product description is required.");
        Validation.RequireField("Price", "Product price is required.");
    
        var db = Database.Open("SmallBakery");
        var Name = Request.Form["Name"];
        var Description = Request.Form["Description"];
        var Price = Request.Form["Price"];
    
        if (IsPost && Validation.IsValid()) {
            // Define the insert query. The values to assign to the
            // columns in the Product table are defined as parameters
            // with the VALUES keyword.
            if(ModelState.IsValid) {
                var insertQuery = "INSERT INTO Product (Name, Description, Price) " +
                    "VALUES (@0, @1, @2)";
                db.Execute(insertQuery, Name, Description, Price);
                // Display the page that lists products.
                Response.Redirect("~/ListProducts");
            }
        }
    }
    
    <!DOCTYPE html>
    <html>
    <head>
     <title>Add Products</title>
     <style type="text/css">
        label {float:left; width: 8em; text-align: right;
               margin-right: 0.5em;}
        fieldset {padding: 1em; border: 1px solid; width: 50em;}
        legend {padding: 2px 4px; border: 1px solid; font-weight:bold;}
        .validation-summary-errors {font-weight:bold; color:red;
               font-size: 11pt;}
     </style>
    </head>
    <body>
     <h1>Add New Product</h1>
    
     @Html.ValidationSummary("Errors with your submission:")
    
     <form method="post" action="">
       <fieldset>
         <legend>Add Product</legend>
         <div>
           <label>Name:</label>
           <input name="Name" type="text" size="50" value="@Name" />
         </div>
         <div>
           <label>Description:</label>
           <input name="Description" type="text" size="50"
               value="@Description" />
         </div>
         <div>
           <label>Price:</label>
           <input name="Price" type="text" size="50" value="@Price" />
         </div>
         <div>
           <label>&nbsp;</label>
           <input type="submit" value="Insert" class="submit" />
         </div>
       </fieldset>
     </form>
    </body>
    </html>
    

    ページの本文に、ユーザーが名前、説明、価格を入力できる 3 つのテキスト ボックスを含む HTML フォームが格納されます。 ユーザーが [挿入] ボタンをクリックすると、ページの上部にあるコードによって、SmallBakery.sdf データベースへの接続が開きます。 次に、Request オブジェクトを使用してユーザーが送信した値を取得し、それらの値をローカル変数に割り当てます。

    ユーザーが必要な列ごとに値を入力したことを検証するには、検証する各 <input> 要素を登録します。

    Validation.RequireField("Name", "Product name is required.");
    Validation.RequireField("Description", "Product description is required.");
    Validation.RequireField("Price", "Product price is required.");
    

    Validation ヘルパーは、登録した各フィールドに値があることを確認します。 すべてのフィールドが検証に合格したかどうかをテストするには、Validation.IsValid() を確認します。これは、ユーザーから取得した情報を処理する前に通常行うテストです。

    if (IsPost && Validation.IsValid()) {
        // Process information here
    }
    

    (&& 演算子は AND を意味します。このテストは、これがフォームの送信であり、かつ、すべてのフィールドが検証に合格したかどうかを判定します)。

    すべての列が検証された場合 (空でなかった場合)、データを挿入する SQL ステートメントを作成し、次に示すように実行します。

    var insertQuery =
        "INSERT INTO Product (Name, Description, Price) VALUES (@0, @1, @2)";
    

    挿入する値には、パラメータ プレースホルダー (@0@1@2) を含めます。

    Note

    セキュリティ上の予防措置として、前の例に示すように、SQL ステートメントに渡す値は、常にパラメータを介します。 これにより、ユーザーのデータを検証できるだけでなく、悪意のあるコマンドをデータベースに送信する試み (SQL インジェクション攻撃とも呼ばれることもあります) から保護できます。

    クエリを実行するには、次のステートメントを使用して、プレースホルダーの代わりに値を含む変数を渡します。

    db.Execute(insertQuery, Name, Description, Price);
    

    Insert Into ステートメントが実行されたら、次の行を使用して、製品を一覧表示するページにユーザーを移動します。

    Response.Redirect("~/ListProducts");
    

    検証が成功しなかった場合は、挿入をスキップします。 代わりに、エラーが発生した場合は蓄積されたエラー メッセージを表示できるヘルパーがページに表示されます。

    @Html.ValidationSummary("Errors with your submission:")
    

    マークアップのスタイル ブロックに、.validation-summary-errors という名前の CSS クラス定義が含まれていることに注目してください。 これは、検証エラーを含む <div> 要素に既定で使用される CSS クラスの名前です。 ここでは、CSS クラスは検証の概要エラーを赤と太字で表示することを指定しますが、.validation-summary-errors クラスを定義すると、任意の書式設定を表示できます。

挿入ページのテスト

  1. ブラウザーでページを表示します。 ページには、次の図に示すようなフォームが表示されます。

    [Screenshot shows a form that will display on the page in a browser.]

  2. すべての列の値を入力しますが、[Price] 列は空白のままにします。

  3. 挿入をクリックします。 次の図に示すように、ページにエラー メッセージが表示されます。 (新しいレコードは作成されません。)

    [Screenshot shows an error message.]

  4. フォームをすべて入力し、[挿入] をクリックします。 今回は、ListProducts.cshtml ページが表示され、新しいレコードが表示されます。

データベース内のデータの更新

テーブルにデータを入力した後、更新が必要になる場合があります。 この手順では、前にデータ挿入用に作成したページと似た 2 つのページを作成する方法を示します。 最初のページには製品が表示され、ユーザーは変更する製品を選択できます。 2 番目のページでは、ユーザーが実際に編集を行って保存できます。

Note

重要: 実稼働用の Web サイトでは、通常、データの変更を許可するユーザーを制限します。 メンバーシップを設定する方法と、ユーザーがサイトでタスクを実行することを承認する方法については、「ASP.NET Web ページ サイトへのセキュリティとメンバーシップの追加」を参照してください。

  1. Web サイトで、EditProducts.cshtml という名前の新しい CSHTML ファイルを作成します。

  2. ファイル内の既存のマークアップを次のように置き換えます。

    @{
        var db = Database.Open("SmallBakery");
        var selectQueryString = "SELECT * FROM Product ORDER BY Name";
    
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title>Edit Products</title>
        <style type="text/css">
            table, th, td {
              border: solid 1px #bbbbbb;
              border-collapse: collapse;
              padding: 2px;
            }
        </style>
    </head>
    <body>
        <h1>Edit Small Bakery Products</h1>
        <table>
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Name</th>
              <th>Description</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            @foreach (var row in db.Query(selectQueryString)) {
              <tr>
                <td><a href="@Href("~/UpdateProducts", row.Id)">Edit</a></td>
                <td>@row.Name</td>
                <td>@row.Description</td>
                <td>@row.Price</td>
              </tr>
            }
          </tbody>
        </table>
    </body>
    </html>
    

    このページと前の ListProducts.cshtml ページとの唯一の違いは、このページの HTML テーブルに、[編集] リンクを表示する追加の列が含まれていることです。 このリンクをクリックすると、選択したレコードを編集できる UpdateProducts.cshtml ページ (次に作成します) に移動します。

    [編集] リンクを作成するコードを確認します。

    <a href="@Href("~/UpdateProducts", row.Id)">Edit</a></td>
    

    これにより、href 属性が動的に設定される HTML <a> 要素が作成されます。 href 属性は、ユーザーがリンクをクリックしたときに表示するページを指定します。 また、現在の行の Id 値もリンクに渡されます。 ページを実行すると、ページ ソースに次のようなリンクが含まれる場合があります。

    <a href="UpdateProducts/1">Edit</a></td>
    <a href="UpdateProducts/2">Edit</a></td>
    <a href="UpdateProducts/3">Edit</a></td>
    

    href 属性が UpdateProducts/n に設定されていることに注意してください。ここで、n は製品番号です。 ユーザーがこれらのリンクのいずれかをクリックすると、結果の URL は次のようになります。

    http://localhost:18816/UpdateProducts/6

    つまり、編集する製品番号が URL に渡されます。

  3. ブラウザーでページを表示します。 ページには、次のような形式でデータが表示されます。

    [Screenshot shows the data displayed on the page in the browser.]

    次に、ユーザーが実際にデータを更新できるページを作成します。 更新ページには、ユーザーが入力したデータを検証するための検証が含まれています。 たとえば、ページ内のコードでは、すべての必須列に対して値が入力されていることを確認します。

  4. Web サイトで、UpdateProducts.cshtml という名前の新しい CSHTML ファイルを作成します。

  5. ファイル内の既存のマークアップを次のように置き換えます。

    @{
        Validation.RequireField("Name", "Product name is required.");
        Validation.RequireField("Description", "Product description is required.");
        Validation.RequireField("Price", "Product price is required.");
    
        var Name = "";
        var Description = "";
        var Price = Decimal.Zero;
    
        var ProductId  = UrlData[0];
        if (ProductId.IsEmpty()) {
             Response.Redirect("~/EditProducts");
        }
    
        var db = Database.Open("SmallBakery");
    
        if (IsPost && Validation.IsValid()) {
            var updateQueryString =
                "UPDATE Product SET Name=@0, Description=@1, Price=@2 WHERE Id=@3" ;
            Name = Request["Name"];
            Description = Request["Description"];
            Price = Request["Price"].AsDecimal();
            db.Execute(updateQueryString, Name, Description, Price, ProductId);
            Response.Redirect(@Href("~/EditProducts"));
        }
        else {
            var selectQueryString = "SELECT * FROM Product WHERE Id=@0";
    
            var row = db.QuerySingle(selectQueryString, ProductId);
            Name = row.Name;
            Description = row.Description;
            Price = row.Price;
        }
    
    }
    
    <!DOCTYPE html>
    <html>
    <head>
      <title>Add Products</title>
      <style type="text/css">
         label { float: left; width: 8em; text-align: right;
                 margin-right: 0.5em;}
         fieldset { padding: 1em; border: 1px solid; width: 35em;}
         legend { padding: 2px 4px;  border: 1px solid; font-weight: bold;}
         .validation-summary-errors {font-weight:bold; color:red; font-size:11pt;}
      </style>
    </head>
    <body>
      <h1>Update Product</h1>
       @Html.ValidationSummary("Errors with your submission:")
       <form method="post" action="">
         <fieldset>
           <legend>Update Product</legend>
           <div>
             <label>Name:</label>
             <input name="Name" type="text" size="50" value="@Name" />
           </div>
           <div>
             <label>Description:</label>
             <input name="Description" type="text" size="50"
                value="@Description" />
           </div>
           <div>
              <label>Price:</label>
              <input name="Price" type="text" size="50" value="@Price" />
           </div>
           <div>
              <label>&nbsp;</label>
              <input type="submit" value="Update" class="submit" />
           </div>
        </fieldset>
      </form>
    </body>
    </html>
    

    ページ本文に製品が表示され、ユーザーが編集できる HTML フォームが含まれます。 製品を表示するには、次の SQL ステートメントを使用します。

    SELECT * FROM Product WHERE Id=@0
    

    これにより、@0 パラメータで渡された値と一致する ID を持つ製品が選択されます。 (Id は主キーであるため、一意である必要があります。したがって、この方法で選択できる製品レコードは 1 つだけです)。この Select ステートメントに渡す ID 値を取得するには、次の構文を使用して、URL の一部としてページに渡される値を読み取れます。

    var ProductId  = UrlData[0];
    

    製品レコードを実際にフェッチするには、QuerySingle メソッドを使用します。このメソッドは、レコードを 1 つだけ返します。

    var row = db.QuerySingle(selectQueryString, ProductId);
    

    1 行が row 変数に返されます。 各列からデータを取得し、次のようにローカル変数に割り当てることができます。

    var Name = row.Name;
    var Description = row.Description;
    var Price = row.Price;
    

    フォームのマークアップでは、次のような埋め込みコードを使用して、これらの値が個々のテキスト ボックスに自動的に表示されます。

    <input name="Name" type="text" size="50" value="@Name" />
    

    コードのその部分には、更新する製品レコードが表示されます。 レコードが表示されたら、ユーザーは個々の列を編集できます。

    ユーザーが [更新] ボタンをクリックしてフォームを送信すると、if(IsPost) ブロック内のコードが実行されます。 これにより、Request オブジェクトからユーザーの値を取得し、その値を変数に格納し、各列が入力されたことを検証します。 検証に合格すると、このコードによって、次の SQL Update ステートメントが作成されます。

    UPDATE Product SET Name=@0, Description=@1, Price=@2, WHERE ID=@3
    

    SQL Update ステートメントでは、更新する各列と、それに設定する値を指定します。 このコードでは、パラメータのプレースホルダー @0@1@2 などを使用して値を指定します。 (前に説明したように、セキュリティのためには、常にパラメータを使用して SQL ステートメントに値を渡す必要があります)。

    db.Execute メソッドを呼び出すときに、SQL ステートメントのパラメータに対応する順序で値を格納する変数を渡します。

    db.Execute(updateQueryString, Name, Description, Price, ProductId);
    

    Update ステートメントが実行されたら、ユーザーを編集ページにリダイレクトするために、次のメソッドを呼び出します。

    Response.Redirect(@Href("~/EditProducts"));
    

    その結果、ユーザーはデータベース内のデータの更新された一覧を表示し、別の製品を編集できます。

  6. ページを保存します。

  7. 更新ページでなく、EditProducts.cshtml ページを実行し、[編集] を選択して、編集する製品を選択します。 UpdateProducts.cshtml ページが表示され、選択したレコードが表示されます。

    [Screenshot shows the Update Products page, along with the selected record.]

  8. 変更を加え、[更新] を選択します。 製品の一覧が、更新されたデータと共に再び表示されます。

データベース内のデータの削除

このセクションでは、ユーザーが Product データベース テーブルから製品を削除できるようにする方法について説明します。 この例は、2 つのページで構成されています。 最初のページでは、ユーザーは削除するレコードを選択します。 その後、2 番目のページに削除するレコードが表示され、レコードを削除することを確認できます。

Note

重要: 実稼働用の Web サイトでは、通常、データの変更を許可するユーザーを制限します。 メンバーシップを設定する方法と、ユーザーがサイトでタスクを実行することを承認する方法については、「ASP.NET Web ページ サイトへのセキュリティとメンバーシップの追加」を参照してください。

  1. Web サイトで、ListProductsForDelete.cshtml という名前の新しい CSHTML ファイルを作成します。

  2. 既存のマークアップを次に置き換えます。

    @{
      var db = Database.Open("SmallBakery");
      var selectQueryString = "SELECT * FROM Product ORDER BY Name";
    }
    <!DOCTYPE html>
    <html>
    <head>
        <title>Delete a Product</title>
        <style>
            table, th, td {
              border: solid 1px #bbbbbb;
              border-collapse: collapse;
              padding: 2px;
            }
         </style>
    </head>
    <body>
      <h1>Delete a Product</h1>
      <form method="post" action="" name="form">
        <table border="1">
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Name</th>
              <th>Description</th>
              <th>Price</th>
            </tr>
          </thead>
          <tbody>
            @foreach (var row in db.Query(selectQueryString)) {
              <tr>
                <td><a href="@Href("~/DeleteProduct", row.Id)">Delete</a></td>
                <td>@row.Name</td>
                <td>@row.Description</td>
                <td>@row.Price</td>
              </tr>
            }
          </tbody>
        </table>
      </form>
    </body>
    </html>
    

    このページは、前の EditProducts.cshtml ページに似ています。 ただし、各製品の [編集] リンクを表示する代わりに、[削除] リンクが表示されます。 [削除] リンクは、マークアップに次の埋め込みコードを使用して作成されます。

    <a href="@Href("~/DeleteProduct", row.Id)">Delete</a>
    

    ユーザーがリンクをクリックすると、次のような URL が作成されます。

    http://<server>/DeleteProduct/4

    この URL は、DeleteProduct.cshtml (次に作成します) という名前のページを呼び出し、削除する製品の ID (ここでは 4) を渡します。

  3. ファイルを保存しますが、開いたままにします。

  4. DeleteProduct.cshtml という名前の別の CHTML ファイルを作成します。 既存のコンテンツを次に置き換えます。

    @{
      var db = Database.Open("SmallBakery");
      var ProductId = UrlData[0];
      if (ProductId.IsEmpty()) {
        Response.Redirect("~/ListProductsForDelete");
      }
      var prod = db.QuerySingle("SELECT * FROM PRODUCT WHERE ID = @0", ProductId);
      if( IsPost && !ProductId.IsEmpty()) {
        var deleteQueryString = "DELETE FROM Product WHERE Id=@0";
        db.Execute(deleteQueryString, ProductId);
        Response.Redirect("~/ListProductsForDelete");
      }
    }
    
    <!DOCTYPE html>
    <html>
    <head>
        <title>Delete Product</title>
    </head>
    <body>
      <h1>Delete Product - Confirmation</h1>
      <form method="post" action="" name="form">
        <p>Are you sure you want to delete the following product?</p>
    
        <p>Name: @prod.Name <br />
           Description: @prod.Description <br />
           Price: @prod.Price</p>
        <p><input type="submit" value="Delete" /></p>
      </form>
    </body>
    </html>
    

    このページは ListProductsForDelete.cshtml によって呼び出され、ユーザーが製品を削除することを確認できます。 削除する製品を一覧表示するには、次のコードを使用して、URL から削除する製品の ID を取得します。

    var ProductId = UrlData[0];
    

    その後、このページで、実際にレコードを削除するにはボタンをクリックするようにユーザーに求められます。 これは重要なセキュリティ対策です。Web サイトでデータの更新や削除などの機密性の高い操作を実行する場合、これらの操作は常に GET 操作でなく POST 操作を使用して実行する必要があります。 GET 操作を使用して削除操作を実行できるようにサイトが設定されている場合は、だれでも http://<server>/DeleteProduct/4 などの URL を渡し、データベースから目的のレコードを削除できます。 確認を追加し、POST を使用してのみ削除を実行できるようにページをコーディングすることで、サイトにセキュリティ対策を追加します。

    実際の削除操作は次のコードを使用して実行されます。このコードでは、最初にこれが事後操作であり、ID が空ではないことを確認します。

    if( IsPost && !ProductId.IsEmpty()) {
        var deleteQueryString = "DELETE FROM Product WHERE Id=@0";
        db.Execute(deleteQueryString, ProductId);
        Response.Redirect("~/ListProductsForDelete");
    }
    

    次に、このコードは、指定したレコードを削除する SQL ステートメントを実行し、ユーザーをリスト ページにリダイレクトします。

  5. ブラウザーで ListProductsForDelete.cshtml を実行します。

    [Screenshot shows running list products for delete dot CSHTML in the browser.]

  6. いずれかの製品の [削除] リンクをクリックします。 DeleteProduct.cshtml ページが表示され、そのレコードを削除することを確認します。

  7. [削除] ボタンをクリックします。 製品レコードが削除され、ページが更新された製品一覧で更新されます。

ヒント

データベースへの接続

データベースには 2 つの方法で接続できます。 1 つ目は、Database.Open メソッドを使用し、データベース ファイルの名前を指定する方法です (.sdf 拡張子を除く)。

var db = Database.Open("SmallBakery");

Open メソッドは、.sdf ファイルが Web サイトの App_Data フォルダーにあることを前提としています。 このフォルダーは、データを保持するために特別に設計されています。 たとえば、Web サイトにデータの読み取りと書き込みを許可する適切なアクセス許可が設定され、セキュリティ対策として、WebMatrix はこのフォルダーからファイルへのアクセスを許可しません。

2 つ目は、接続文字列を使用する方法です。 データベースに接続する方法に関する情報が含まれる接続文字列。 これには、ファイル パスを含められ、ローカル サーバーまたはリモート サーバー上の SQL Server データベースの名前と、そのサーバーに接続するためのユーザー名とパスワードも含められます。 (ホスティング プロバイダーのサイトなど、一元管理された SQL Server にデータを保存する場合は必ず接続文字列を使用し、データベース接続情報を指定します)。

WebMatrix では、通常接続文字列は Web.config という名前の XML ファイルに格納されます。名前が示すように、Web サイトのルートにある Web.config ファイルを使用して、サイトに必要な可能性がある接続文字列など、サイトの構成情報を格納できます。 Web.config ファイル内の接続文字列の例を次に示します。 $CREDENTIAL_PLACEHOLDER$ が、パスワード キーと値のペアのプレースホルダーであることに注意してください。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
   <add
     name="SQLServerConnectionString"
     connectionString= "server=myServer;database=myDatabase;uid=username;$CREDENTIAL_PLACEHOLDER$"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

この例では、接続文字列は、ローカル .sdf ファイルでなく、どこかリモートのサーバーで実行されている SQL Server のインスタンス内のデータベースを指しています。 myServermyDatabase を適切な名前に置き換え、usernamepassword に SQL Server ログイン値を指定する必要があります。 (このユーザー名とパスワードの値は、ご利用の Windows 資格情報や、ホスティング プロバイダーがサーバーにログインするために提供した値と必ずしも同じではありません。必要な正確な値については、管理者に問い合わせてください)。

Database.Open メソッドには、データベース .sdf ファイルの名前を渡すか、Web.config ファイルに格納されている接続文字列の名前を渡すかのどちらにも対応する柔軟性があります。 次の例は、前の例で示した接続文字列を使用してデータベースに接続する方法を示しています。

@{
    var db = Database.Open("SQLServerConnectionString");
}

前に説明したように、Database.Open メソッドを使用すると、データベース名または接続文字列を渡すことができ、メソッドがどちらを使用するかを判断できます。 これは、Web サイトをデプロイ (発行) するときに非常に便利です。 サイトを開発およびテストするときに、App_Data フォルダー内の .sdf ファイルを使用できます。 その後、サイトを実稼働サーバーに移動するときに、.sdf ファイルと同じ名前を持つ接続文字列を Web.config ファイルで使用できますが、ホスティング プロバイダーのデータベースを指すため、コードを変更する必要はありません。

最後に、接続文字列を直接操作する場合は、Database.OpenConnectionString メソッドを呼び出し、Web.config ファイル内の接続文字列名の代わりに、実際の接続文字列を渡すことができます。 これは、何らかの理由で、ページが実行されるまでは接続文字列 (または .sdf ファイル名などのその中の値) にアクセスできない場合に役立ちます。 ただし、ほとんどのシナリオでは、この記事の説明に従って、Database.Open を使用できます。

その他のリソース