Web アプリケーション (ASP.NET) でDBを更新してみよう(VS2005 TableAdapter 編)

VS2003 DataAdapter 編 につづいて、VS2005 の TableAdapter を使って、DataBase へのアクセスします。
こちらで最終的に実現したい事は、VS2003 DataAdapter 編とほぼ同じです。
※今回は、プロジェクト名を MyWebDBApp05 としました。
※解説に用いた Visual Studio 2005 の Edition は、Team System Edition です。
サンプルのダウンロード

このカテゴリーの先頭へ このページの先頭へ

■プロジェクトの作成 〜 Web Page に GridView を配置する

Web アプリケーション (ASP.NET) でDBのデータを表示しよう(VS2005 TableAdapter 編)にて行った事と全く同じ事をします。
プロジェクトの作成
データ接続の作成
Table Adapter の作成
Web Page に GridView を配置する

このカテゴリーの先頭へ このページの先頭へ

■オブジェクト データソース の作成

ツールボックス(表示されていない場合は、メニューバーの[表示]→[ツールボックス]をクリックして表示させてくださいね)の
[データ]タブの中にある、ObjectDataSource を、デザイナ上の Web Page にドラッグします。
ObjectDataSource の作成

Web Page 上に配置された ObjectDataSource の右上端にある、三角のボタンをクリックすると、
データ ソースの構成というリンクが表示されますので、そのリンクをクリックします。
ObjectDataSource の作成

[データソースの構成ウィザード]が始まります。
ビジネス オブジェクト の選択
ここでは、先に作成した TableAdapter (CustomersTableAdapters.CustomersTableAdapter)を選択します。

[データ メソッドの定義]では、DB に対して SELECT・UPDATE・INSERT・DELETE を行うメソッドを決定します。
おそらく、デフォルトで選択されています。内容を確認し、必要があれば変更します。
データ メソッドの定義
完了ボタンを押下すると、[データソースの構成ウィザード]は終了します。

ObjectDataSource の設定は終わりです。

このカテゴリーの先頭へ このページの先頭へ

■GridView のプロパティを編集する

GridView を選択して、プロパティ ウィンドウ(表示されていない場合は、メニューバーの[表示]→[プロパティ ウィンドウ]をクリックして表示させてくださいね)の
AutoGenerateColumns の値を False にします。

Web Page 上に配置された GridView の右上端にある、三角のボタンをクリックすると、
データ ソースの選択というドロップダウンがありますので、そこで 前述で作成した ObjectDataSource を選択します。
データ ソースの選択

GridView の右上端にある、三角のボタンをクリックすると、列の編集 というリンクがあるので、クリックします。

列の編集 → フィールド ダイアログ
[使用可能なフィールド] から (すべてのフィールド) または BoundField → 任意の列 を選択し、[追加]ボタンを押下して [選択されたフィールド] に追加します。
選択された列の内、主キー フィールド 以外の列を一つ一つをクリックし、フィールド ダイアログ の下のほうにある [この列を TemplateField に変換します。] というリンクをクリックします。
同様に、ボタン列 → [編集、更新、キャンセル] と [削除] を [選択されたフィールド] に追加します。
[OK]ボタンを押下し、フィールド ダイアログを閉じます。
# [削除]等 を TemplateField に変換し、GridView 右クリック → テンプレートの編集 で、OnClientClick に 確認メッセージを表示する事等もできます。

このカテゴリーの先頭へ このページの先頭へ

■コードを入力

今回はコードビハインド(Default.aspx.vb)にコードを書く必要はありません。
ちなみに、Default.aspx は以下の様になっています。

Default.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>無題のページ</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="Delete"
            InsertMethod="Insert" OldValuesParameterFormatString="original_{0}" SelectMethod="GetData"
            TypeName="CustomersTableAdapters.CustomersTableAdapter" UpdateMethod="Update">
            <DeleteParameters>
                <asp:Parameter Name="Original_CustomerID" Type="String" />
            </DeleteParameters>
            <UpdateParameters>
                <asp:Parameter Name="CompanyName" Type="String" />
                <asp:Parameter Name="ContactName" Type="String" />
                <asp:Parameter Name="Phone" Type="String" />
                <asp:Parameter Name="Fax" Type="String" />
                <asp:Parameter Name="Original_CustomerID" Type="String" />
                <asp:Parameter Name="CustomerID" Type="String" />
            </UpdateParameters>
            <InsertParameters>
                <asp:Parameter Name="CustomerID" Type="String" />
                <asp:Parameter Name="CompanyName" Type="String" />
                <asp:Parameter Name="ContactName" Type="String" />
                <asp:Parameter Name="Phone" Type="String" />
                <asp:Parameter Name="Fax" Type="String" />
            </InsertParameters>
        </asp:ObjectDataSource>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="CustomerID" DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" SortExpression="CustomerID" />
                <asp:TemplateField HeaderText="CompanyName" SortExpression="CompanyName">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("CompanyName") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%# Bind("CompanyName") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="ContactName" SortExpression="ContactName">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("ContactName") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label2" runat="server" Text='<%# Bind("ContactName") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Phone" SortExpression="Phone">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("Phone") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label3" runat="server" Text='<%# Bind("Phone") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Fax" SortExpression="Fax">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox4" runat="server" Text='<%# Bind("Fax") %>'></asp:TextBox>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label4" runat="server" Text='<%# Bind("Fax") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:CommandField ShowEditButton="True" />
                <asp:TemplateField ShowHeader="False">
                    <ItemTemplate>
                        <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Delete"
                            OnClientClick="return confirm('本当に削除しても良いですか?')" Text="削除"></asp:LinkButton>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        &nbsp;</div>
    </form>
</body>
</html>

データ接続を作成する際、SQL Server への認証を「Windows 認証」にしました。
ASP.NET の場合は、実行時に SQL Server へログオンするのは、ASPNET ユーザーになります。
その為、SQL Server にログインする権限がないとエラーが発生します。
ASPNET ユーザーに権限を与える方法もありますが、通常は "偽装" と呼ばれるテクニックを使います。
偽装をする為にもっともポピュラーな方法は、web.config ファイルに以下の一文を追記します。

<identity impersonate="true" userName="SQL Server にアクセスできる権限のあるユーザー名" password="userName に記述したユーザーの Windows ログオンパスワード" />
このカテゴリーの先頭へ このページの先頭へ

■実行しよう!

メニューバーの[デバッグ]→[デバッグ開始]をクリックして実行します。
↓こんな画面が出現しましたか?
実行結果
上のような画面が出現したら、編集→キャンセル・編集→更新・削除と一通りやってみてください。
SQL Server 側の該当テーブルで データの内容が 画面表示と同じになっていれば大成功です。
画面右上の×ボタンをクリックしてプログラムを終了させて下さい。

このカテゴリーの先頭へ このページの先頭へ

■ひとこと

結構かんたんに実装できます。
値のチェック等をしたい場合は、GridView の RowUpdating イベントや RowDeleting イベント等で行えばよいでしょう。

といいつつも実は、今回はものすごくハマりました。
更新や削除をしようとすると、
「ObjectDataSource 'ObjectDataSource1' では、パラメータ ... を含む非ジェネリック メソッド 'Update' が見つかりませんでした。」
と言われて、TableAdapter 構成ウィザードで作ったメソッドの事を言われても... ObjectDataSource にはちゃんと設定したし... てな感じで調べていましたが、
ObjectDataSource could not find a non-generic method Update Error にたどり着きました。
対策としてこのような事が書かれています。
1) Don’t make the keys ReadOnly. Bad. Bad. Bad. Mega Lame.
  → キー項目を ReadOnly にしないでください。
2) Modify the Update query (by hand) so that it doesn’t update the key columns.
  → キー項目を Update しないように Update 文を(手で)修正してください。

ふむ...。
書かれているとおりに キー項目の ReadOnly をやめて、Customers DataSet の Customers DataTable の UpdateCommand・DeleteCommand を デザイナ上で編集しました。
そうしたら動くようになったんですが、ホントにこうしないとダメなのかしら...

ここでは触れていませんが、追加については どっとねっとふぁん小野さんがわかりやすいエントリをされていますので、こちらを参考にして下さい。
GridViewからデータを追加する@どっとねっとふぁんBlog

このカテゴリーの先頭へ このページの先頭へ