パラメーター化されたクエリと SqlDataSource を使用する (VB)

作成者: Scott Mitchell

PDF のダウンロード

このチュートリアルでは、引き続き SqlDataSource コントロールを確認し、パラメーター化されたクエリを定義する方法について説明します。 パラメーターは、宣言とプログラムの両方によって指定でき、クエリ文字列、セッション状態、その他のコントロールなど、さまざまな場所からプルできます。

はじめに

前のチュートリアルでは、SqlDataSource コントロールを使用してデータベースから直接データを取得する方法について説明しました。 データ ソースの構成ウィザードを使用して、データベースを選択し、テーブルまたはビューから返す列を選択するか、カスタム SQL ステートメントを入力するか、ストアド プロシージャを使用します。 テーブルまたはビューから列を選択するか、カスタム SQL ステートメントを入力するかに関係なく、SqlDataSource コントロールの SelectCommand プロパティには、結果として生成されるアドホック SQL SELECT ステートメントが割り当てられます。これは、SqlDataSource の Select() メソッドが (プログラムによって、またはデータ Web コントロールから自動的に) 呼び出されたときに実行される SELECT ステートメントです。

前のチュートリアルのデモで使用した SQL SELECT ステートメントには WHERE 句がありませんでした。 SELECT ステートメントでは、返される結果を制限するために WHERE 句を使用できます。 たとえば、50.00 ドルを超える製品の名前を表示するために、次のクエリを使用できます。

SELECT ProductName
FROM Products
WHERE UnitPrice > 50.00

通常、WHERE 句で使用される値は、クエリ文字列値、セッション変数、ページ上の Web コントロールからのユーザー入力など、いくつかの外部ソースによって決まります。 このような入力は、"パラメーター" を使用して指定するのが理想です。 Microsoft SQL Server では、パラメーターは次のように @parameterName を使用して示されます。

SELECT ProductName
FROM Products
WHERE UnitPrice > @Price

SqlDataSource では、SELECT ステートメントと、INSERTUPDATEDELETE ステートメントの両方で、パラメーター化されたクエリがサポートされます。 さらに、パラメーター値は、クエリ文字列、セッション状態、ページ上のコントロールなどのさまざまなソースから自動的にプルしたり、プログラムによって割り当てたりすることができます。 このチュートリアルでは、パラメーター化されたクエリを定義する方法と、宣言とプログラムの両方によってパラメーター値を指定する方法について説明します。

Note

前のチュートリアルでは、最初の 46 個のチュートリアルで選択した ObjectDataSource を SqlDataSource と比較し、その概念の類似点を確認しました。 これらの類似点は、パラメーターにも及びます。 ビジネス ロジック レイヤー内のメソッドの入力パラメーターにマップされた ObjectDataSource のパラメーター。 SqlDataSource では、パラメーターは SQL クエリ内で直接定義されます。 どちらのコントロールにも、Select()Insert()Update()Delete() メソッドのパラメーターのコレクションがあり、どちらも、定義済みのソース (クエリ文字列値、セッション変数など) からこれらのパラメーター値を設定したり、プログラムによって割り当てたりすることができます。

パラメーター クエリの作成

SqlDataSource コントロールのデータ ソースの構成ウィザードには、データベース レコードを取得するために実行するコマンドを定義するための次の 3 つの手段があります。

  • 既存のテーブルまたはビューから列を選択する
  • カスタム SQL ステートメントを入力する
  • ストアド プロシージャを選択する

既存のテーブルまたはビューから列を選択する場合は、[WHERE 句の追加] ダイアログ ボックスで WHERE 句のパラメーターを指定する必要があります。 ただし、カスタム SQL ステートメントを作成する場合は、(各パラメーターを示すために WHERE を使用して) パラメーターを @parameterName 句に直接入力できます。 ストアド プロシージャは 1 つ以上の SQL ステートメントで構成され、これらのステートメントはパラメーター化できます。 ただし、SQL ステートメントで使用されるパラメーターは、ストアド プロシージャに入力パラメーターとして渡す必要があります。

パラメーター化されたクエリの作成方法は、SqlDataSource の SelectCommand をどのように指定するかによって変わるため、3 つのアプローチをすべて見てみましょう。 作業を開始するには、SqlDataSource フォルダー内の ParameterizedQueries.aspx ページを開き、ツールボックスからデザイナーに SqlDataSource コントロールをドラッグし、IDProducts25BucksAndUnderDataSource に設定します。 次に、コントロールのスマート タグの [データ ソースの構成] リンクをクリックします。 使用するデータベース (NORTHWINDConnectionString) を選択し、[次へ] をクリックします。

ステップ 1: テーブルまたはビューから列を選択するときの WHERE 句を追加する

SqlDataSource コントロールを使用してデータベースから返すデータを選択する場合、データ ソースの構成ウィザードで既存のテーブルまたはビューから返す列を選択することができます (図 1 を参照)。 これにより、SQL SELECT ステートメントが自動的に作成されます。これは、SqlDataSource の Select() メソッドが呼び出されるとデータベースに送信されます。 前のチュートリアルで行ったように、ドロップダウン リストから Products テーブルを選んで、ProductIDProductNameUnitPrice 列をオンにします。

Pick the Columns to Return from a Table or View

図 1: テーブルまたはビューから返す列を選択する (クリックするとフルサイズの画像が表示されます)

SELECT ステートメントに WHERE 句を含めるには、WHERE ボタンをクリックします。そうすると、[WHERE 句の追加] ダイアログ ボックスが表示されます (図 2 を参照)。 SELECT クエリによって返される結果を制限するパラメーターを追加するにはまず、データをフィルター処理する列を選択します。 次に、フィルター処理に使用する演算子 (=、<、<=、> など) を選択します。 最後に、クエリ文字列やセッション状態など、パラメーターの値のソースを選択します。 パラメーターを構成したら、[追加] ボタンをクリックして SELECT クエリに含めます。

この例では、UnitPrice の値が $25.00 以下の結果のみを返します。 したがって、[列] ドロップダウン リストから UnitPrice を選び、[演算子] ドロップダウン リストから <= を選びます。 ハードコーディングされたパラメーター値 ($25.00 など) を使用する場合や、パラメーター値をプログラムによって指定する場合は、[ソース] ドロップダウン リストから [なし] を選択します。 その後、[値] テキストボックスにハードコーディングされたパラメーター値 25.00 を入力し、[追加] ボタンをクリックしてプロセスを完了します。

Limit the Results Returned from the Add WHERE Clause Dialog Box

図 2: [WHERE 句の追加] ダイアログ ボックスから返される結果を制限する (クリックするとフルサイズの画像が表示されます)

パラメーターを追加したら、[OK] をクリックしてデータ ソースの構成ウィザードに戻ります。 ウィザードの下部にある SELECT ステートメントに、@UnitPrice という名前のパラメーターを含む WHERE 句が含まれるようになりました。

SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)

Note

[WHERE 句の追加] ダイアログ ボックスで WHERE 句に複数の条件を指定すると、ウィザードによって AND 演算子と結合されます。 WHERE 句に OR を含める必要がある場合は (WHERE UnitPrice <= @UnitPrice OR Discontinued = 1 など)、カスタム SQL ステートメント画面を使って SELECT ステートメントを作成する必要があります。

SqlDataSource の構成を完了し ([次へ]、[完了] の順にクリック)、SqlDataSource の宣言型マークアップを調べます。 マークアップに <SelectParameters> コレクションが含まれるようになりました。これにより、パラメーターのソースが SelectCommand にスペル アウトされます。

<asp:SqlDataSource ID="Products25BucksAndUnderDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice]
        FROM [Products] WHERE ([UnitPrice] <= @UnitPrice)">
    <SelectParameters>
        <asp:Parameter DefaultValue="25.00" Name="UnitPrice" Type="Decimal" />
    </SelectParameters>
</asp:SqlDataSource>

SqlDataSource の Select() メソッドが呼び出されると、データベースに送信される前の SelectCommand@UnitPrice パラメーターに UnitPrice パラメーターの値 (25.00) が適用されます。 その結果、$25.00 以下の製品のみが Products テーブルから返されるようになります。 これを確認するには、ページに GridView を追加し、このデータ ソースにバインドしてから、ブラウザーを使用してページを表示します。 図 3 に示すように、25.00 ドル以下の製品のみが表示されます。

Only Those Products Less Than or Equal to $25.00 are Displayed

図 3: $25.00 以下の製品のみが表示される (クリックするとフルサイズの画像が表示されます)

ステップ 2: カスタム SQL ステートメントにパラメーターを追加する

カスタム SQL ステートメントを追加する場合は、WHERE 句を明示的に入力するか、クエリ ビルダーの [フィルター] セルで値を指定できます。 これを示すために、価格が特定のしきい値より小さい製品だけを GridView に表示してみましょう。 まず、TextBox を ParameterizedQueries.aspx ページに追加して、ユーザーからこのしきい値を収集します。 TextBox の ID プロパティを MaxPrice に設定します。 Button Web コントロールを追加し、その Text プロパティを [一致する製品の表示] に設定します。

次に、GridView をページにドラッグし、そのスマート タグから ProductsFilteredByPriceDataSource という名前の新しい SqlDataSource を選択して作成します。 データ ソースの構成ウィザードから、[カスタム SQL ステートメントまたはストアド プロシージャを指定する] 画面 (図 4 を参照) に進み、次のクエリを入力します。

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0

(手動またはクエリ ビルダーを使用して) クエリを入力した後、[次へ] をクリックします。

Return Only Those Products Less Than or Equal to a Parameter Value

図 4: パラメーター値以下の製品のみが返される (クリックするとフルサイズの画像が表示されます)

クエリにはパラメーターが含まれるため、ウィザードの次の画面でパラメーター値のソースの入力を求められます。 [パラメーター ソース] ドロップダウン リストから [コントロール] を選択し、[ControlID] ドロップダウン リストから MaxPrice (TextBox コントロールの ID 値) を選択します。 ユーザーが MaxPrice TextBox にテキストを入力していない場合に使用する省略可能な既定値を入力することもできます。 当面は、既定値を入力しないでください。

The MaxPrice TextBox s Text Property is Used as the Parameter Source

図 5: パラメーター ソースとして MaxPrice TextBox の Text プロパティを使用する (クリックするとフルサイズの画像が表示されます)

[次へ]、[完了] の順にクリックして、データ ソースの構成ウィザードを完了します。 GridView、TextBox、Button、SqlDataSource の宣言型マークアップは次のとおりです。

Maximum price:
$<asp:TextBox ID="MaxPrice" runat="server" Columns="5" />
 
<asp:Button ID="DisplayProductsLessThanButton" runat="server"
    Text="Display Matching Products" />
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataSourceID="ProductsFilteredByPriceDataSource" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            HtmlEncode="False" DataFormatString="{0:c}"
            SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsFilteredByPriceDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand=
        "SELECT ProductName, UnitPrice 
        FROM Products WHERE UnitPrice <= @MaximumPrice">
    <SelectParameters>
        <asp:ControlParameter ControlID="MaxPrice" Name="MaximumPrice"
            PropertyName="Text" />
    </SelectParameters>
</asp:SqlDataSource>

SqlDataSource の <SelectParameters> セクション内のパラメーターは、ControlIDPropertyName のような追加のプロパティを含む ControlParameter であることに注意してください。 SqlDataSource の Select() メソッドが呼び出されると、ControlParameter は指定した Web コントロール プロパティから値を取得し、SelectCommand 内の対応するパラメーターに割り当てます。 この例では、MaxPrice の Text プロパティが @MaxPrice パラメーター値として使用されます。

ブラウザーでこのページを表示するには、少し時間がかかります。 最初にページにアクセスした場合や、TextBox に MaxPrice 値がない場合は常に、GridView にレコードが表示されません。

No Records are Displayed When the MaxPrice TextBox is Empty

図 6: MaxPrice TextBox が空の場合、レコードは表示されない (クリックするとフルサイズの画像が表示されます)

製品が表示されないのは、パラメーター値の空の文字列が既定でデータベースの NULL 値に変換されるためです。 [UnitPrice] <= NULL の比較は常に False と評価されるため、結果は返されません。

テキストボックスに値 (5.00 など) を入力し、[一致する製品の表示] ボタンをクリックします。 ポストバック時に、SqlDataSource はパラメーター ソースの 1 つが変更されたことを GridView に通知します。 その結果、GridView が SqlDataSource に再バインドされ、$5.00 以下の製品が表示されます。

Products Less Than or Equal to $5.00 are Displayed

図 7: $5.00 以下の製品が表示される (クリックするとフルサイズの画像が表示されます)

最初にすべての製品を表示する

ページが最初に読み込まれたときに製品が表示されないようにするのではなく、"すべての" 製品を表示することができます。 MaxPrice TextBox が空の場合に常にすべての製品を一覧表示する方法の 1 つは、パラメーターの既定値を 1000000 のような非常に高い値に設定することです。Northwind Traders が単価が 1,000,000 ドルを超えるインベントリを持つ可能性は低いためです。 ただし、このアプローチはその場しのぎであり、他の状況では機能しない可能性があります。

宣言型パラメーターDropDownList を使用したマスターと詳細フィルター処理に関する前のチュートリアルでも、同様の問題が発生しました。 そのときの解決策は、このロジックをビジネス ロジック層に置くことでした。 具体的には、BLL によって入力値が調べられ、それが NULL または予約されている値である場合、呼び出しはすべてのレコードを返す DAL メソッドにルーティングされました。 入力値が通常のフィルター値の場合は、パラメーター化された WHERE 句と指定された値を使う SQL ステートメントを実行する DAL メソッドに対して、呼び出しが行われました。

残念ながら、SqlDataSource を使うときはそのアーキテクチャをバイパスします。 代わりに、@MaximumPrice パラメーターが NULL または予約されている値の場合は、すべてのレコードをインテリジェントに取得するように、SQL ステートメントをカスタマイズする必要があります。 この演習では、@MaximumPrice パラメーターが -1.0 と等しい場合は、"すべての" レコードが返されるようにします (UnitPrice の値が負の製品はないため、-1.0 は予約された値として機能します)。 これを実現するには、次の SQL ステートメントを使用できます。

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice OR @MaximumPrice = -1.0

この WHERE 句は、@MaximumPrice パラメーターが -1.0 と等しい場合、"すべての" レコードを返します。 パラメーター値が -1.0 でない場合は、UnitPrice@MaximumPrice パラメーター値以下の製品のみが返されます。 @MaximumPrice パラメーターの既定値を -1.0 に設定すると、ページが最初に読み込まれるときは (または、MaxPrice TextBox が空のときは常に)、@MaximumPrice の値は -1.0 であり、すべての製品が表示されます。

Now All Products are Displayed When the MaxPrice TextBox is Empty

図 8: MaxPrice TextBox が空の場合、すべての製品が表示されるようになった (クリックするとフルサイズの画像が表示されます)

このアプローチには、いくつかの注意事項があります。 まず、パラメーターのデータ型は、SQL クエリでのその使用法によって推論されることに注意してください。 WHERE 句を @MaximumPrice = -1.0 から @MaximumPrice = -1 に変更すると、ランタイムはパラメーターを整数として扱います。 その後に MaxPrice TextBox を 10 進値 (5.00 など) に割り当てようとすると、5.00 を整数に変換できないため、エラーが発生します。 これを解決するには、WHERE 句で @MaximumPrice = -1.0 を使うようにするか、それより良い方法は、ControlParameter オブジェクトの Type プロパティを Decimal に設定することです。

2 つ目に、OR @MaximumPrice = -1.0WHERE 句に追加すると、クエリ エンジンは UnitPrice のインデックスを使用できないため (存在すると仮定して)、テーブル スキャンが行われます。 このため、Products テーブルのレコードが多い場合、パフォーマンスに影響する可能性があります。 インデックスを使用できるよう、このロジックをストアド プロシージャに移動し、IF ステートメントを使って、SELECT クエリを、WHERE 句なしで Products テーブルから実行されるか (すべてのレコードを返す必要があるとき)、UnitPrice 条件だけを含む WHERE 句を使って実行されるようにすることをお勧めします。

ステップ 3: パラメーター化されたストアド プロシージャを作成して使用する

ストアド プロシージャには、ストアド プロシージャ内で定義された SQL ステートメントに使用できる一連の入力パラメーターを含めることができます。 入力パラメーターを受け入れるストアド プロシージャを使用するように SqlDataSource を構成する場合、これらのパラメーター値をアドホック SQL ステートメントと同じ手法を使用して指定することができます。

SqlDataSource でストアド プロシージャを使用する方法を説明するため、Northwind データベースに GetProductsByCategory という名前の新しいストアド プロシージャを作成します。これは、@CategoryID という名前のパラメーターを受け取り、CategoryID 列が @CategoryID と一致する製品のすべての列を返します。 ストアド プロシージャを作成するには、サーバー エクスプローラーに移動し、NORTHWND.MDF データベースにドリルダウンします。 (サーバー エクスプローラーが表示されない場合は、[表示] メニューに移動し、[サーバー エクスプローラー] オプションを選択します。)

NORTHWND.MDF データベースの [ストアド プロシージャ] フォルダーを右クリックし、[新しいストアド プロシージャの追加] を選んで、次の構文を入力します。

CREATE PROCEDURE dbo.GetProductsByCategory
(
      @CategoryID int
)
AS
SELECT *
FROM Products
WHERE CategoryID = @CategoryID

[保存] アイコンをクリックして (または Ctrl + S キーを押して)、ストアド プロシージャを保存します。 ストアド プロシージャをテストするには、[ストアド プロシージャ] フォルダーでそれを右クリックして [実行] を選びます。 ストアド プロシージャのパラメーター (この場合は @CategoryID) の入力を求められ、その後、結果が [出力] ウィンドウに表示されます。

The GetProductsByCategory Stored Procedure when Executed with a <span class=@CategoryID of 1" />

図 9: @CategoryID が 1 で実行された GetProductsByCategory ストアド プロシージャ (クリックするとフルサイズの画像が表示されます)

このストアド プロシージャを使って、Beverages カテゴリのすべての製品を GridView に表示してみましょう。 ページに新しい GridView を追加し、BeverageProductsDataSource という名前の新しい SqlDataSource にバインドします。 [カスタム SQL ステートメントまたはストアド プロシージャを指定する] 画面に進み、[ストアド プロシージャ] ラジオ ボタンを選んで、ドロップダウン リストから GetProductsByCategory ストアド プロシージャを選びます。

Select the GetProductsByCategory Stored Procedure from the Drop-Down List

図 10: ドロップダウン リストから GetProductsByCategory ストアド プロシージャを選択する (クリックするとフルサイズの画像が表示されます)

このストアド プロシージャは入力パラメーター (@CategoryID) を受け取るため、[次へ] をクリックすると、このパラメーターの値のソースを指定するように求められます。 Beverages の CategoryID は 1 なので、[パラメーター ソース] ドロップダウン リストは [なし] のままにし、[DefaultValue] ボックスに「1」と入力します。

Use a Hard-Coded Value of 1 to Return the Products in the Beverages Category

図 11: ハードコーディングされた値 1 を使用して Beverages カテゴリの製品を返す (クリックするとフルサイズの画像が表示されます)

次の宣言型マークアップで示すように、ストアド プロシージャを使うときは、SqlDataSource の SelectCommand プロパティがストアド プロシージャの名前に設定され、SelectCommandType プロパティStoredProcedure に設定されて、SelectCommand がアドホック SQL ステートメントではなくストアド プロシージャの名前であることが示されます。

<asp:SqlDataSource ID="BeverageProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter DefaultValue="1" Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

ブラウザーでページをテストします。 Beverages カテゴリに属する製品のみが表示されますが、GetProductsByCategory ストアド プロシージャは Products テーブルのすべての列を返すため、"すべての" 製品フィールドが表示されます。 もちろん、GridView の [列の編集] ダイアログ ボックスから GridView に表示されるフィールドを制限またはカスタマイズすることもできます。

All of the Beverages are Displayed

図 12: すべての Beverages が表示される (クリックするとフルサイズの画像が表示されます)

ステップ 4: SqlDataSource の Select() ステートメントをプログラムで呼び出す

前のチュートリアルとこのチュートリアルでここまで見た例では、SqlDataSource コントロールを GridView に直接バインドしました。 ただし、SqlDataSource コントロールのデータは、プログラムでアクセスし、コードで列挙できます。 これは、データを調べるためにクエリを実行する必要があるものの表示する必要はない場合に特に便利です。 データベースに接続し、コマンドを指定して結果を取得するために、すべての定型 ADO.NET コードを記述する必要はなく、SqlDataSource でこの単調なコードを処理することができます。

SqlDataSource のデータをプログラムによって操作する方法を説明するため、ランダムに選択されたカテゴリとその関連製品の名前を表示する Web ページの作成を上司から要求されたとします。 つまり、ユーザーがこのページにアクセスしたら、Categories テーブルからカテゴリをランダムに選び、カテゴリ名を表示して、そのカテゴリに属する製品の一覧を表示します。

これを行うには、2 つの SqlDataSource コントロールが必要です。1 つは Categories テーブルからランダムなカテゴリを取得し、もう 1 つはカテゴリの製品を取得します。 このステップでは、ランダムなカテゴリのレコードを取得する SqlDataSource を作成します。ステップ 5 では、カテゴリの製品を取得する SqlDataSource の作成について説明します。

まず、ParameterizedQueries.aspx に SqlDataSource を追加し、その IDRandomCategoryDataSource に設定します。 次の SQL クエリを使用するように構成します。

SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()

ORDER BY NEWID() は、ランダムな順序で並べ替えられたレコードを返します (「NEWID() をレコードのランダムな並べ替えに使用する」を参照)。 SELECT TOP 1 は、結果セットの最初のレコードを返します。 まとめると、このクエリは、ランダムに選択された 1 つのカテゴリの CategoryID および CategoryName 列の値を返します。

カテゴリの CategoryName の値を表示するため、Label Web コントロールをページに追加し、その ID プロパティを CategoryNameLabel に設定して、その Text プロパティをクリアします。 SqlDataSource コントロールからデータをプログラムによって取得するには、その Select() メソッドを呼び出す必要があります。 このSelect() メソッドでは、DataSourceSelectArguments 型の単一の入力パラメーターが必要です。このパラメーターは、返す前のデータをメッセージ化する方法を指定します。 これには、データの並べ替えとフィルター処理に関する指示を含めることができ、SqlDataSource コントロールからのデータの並べ替えやページングを行うときにデータ Web コントロールによって使われます。 ただし、この例では、返される前のデータを変更する必要がないため、DataSourceSelectArguments.Empty オブジェクトを渡します。

Select() メソッドは、IEnumerable を実装するオブジェクトを返します。 返される正確な型は、SqlDataSource コントロールの DataSourceMode プロパティの値によって異なります。 前のチュートリアルで説明したように、このプロパティは DataSet または DataReader のいずれかの値に設定できます。 DataSet に設定すると、Select() メソッドは DataView オブジェクトを返します。DataReader に設定すると、IDataReader を実装するオブジェクトを返します。 RandomCategoryDataSource SqlDataSource の DataSourceMode プロパティは DataSet (既定値) に設定されているため、DataView オブジェクトを使用します。

次のコードでは、DataView として RandomCategoryDataSource SqlDataSource からレコードを取得する方法と、最初の DataView 行から CategoryName 列の値を読み取る方法を示します。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
    ' Get the data from the SqlDataSource as a DataView
    Dim randomCategoryView As DataView = CType _
        (RandomCategoryDataSource.Select(DataSourceSelectArguments.Empty), DataView)
    If randomCategoryView.Count > 0 Then
        ' Assign the CategoryName value to the Label
        CategoryNameLabel.Text = String.Format( _
            "Here are Products in the {0} Category...", _
            randomCategoryView(0)("CategoryName").ToString())
    End If
End Sub

randomCategoryView(0) は DataView の最初の DataRowView を返します。 randomCategoryView(0)("CategoryName") はこの最初の行の CategoryName 列の値を返します。 DataView は緩やかに型指定されていることに注意してください。 特定の列値を参照するには、列の名前を文字列 (この場合は CategoryName) として渡す必要があります。 図 13 は、ページを表示すると CategoryNameLabel に表示されるメッセージを示しています。 もちろん、表示される実際のカテゴリ名は、ページへのアクセスごとに RandomCategoryDataSource SqlDataSource によってランダムに選択されます (ポストバックを含む)。

The Randomly Selected Category s Name is Displayed

図 13: ランダムに選択されたカテゴリの名前が表示される (クリックするとフルサイズの画像が表示されます)

Note

SqlDataSource コントロールの DataSourceMode プロパティが DataReader に設定されている場合は、Select() メソッドからの戻り値を IDataReader にキャストする必要がありました。 最初の行の CategoryName 列の値を読み取るために、次のようなコードを使用します。

If randomCategoryReader.Read() Then
   Dim categoryName as String = randomCategoryReader("CategoryName').ToString()
   ...
End If

SqlDataSource でカテゴリがランダムに選択されるようになったので、カテゴリの製品を一覧表示する GridView を追加する準備ができました。

Note

Label Web コントロールを使ってカテゴリの名前を表示するのではなく、FormView または DetailsView をページに追加し、それを SqlDataSource にバインドすることもできます。 ただし、Label を使用すると、SqlDataSource の Select() ステートメントをプログラムによって呼び出し、その結果のデータをコードで操作する方法を調べることができます。

ステップ 5: プログラムでパラメーターの値を割り当てる

このチュートリアルでこれまでに見てきたすべての例では、ハードコーディングされたパラメーター値または定義済みのパラメーター ソース (クエリ文字列値、ページ上の Web コントロールなど) から取得したものを使用しています。 ただし、SqlDataSource コントロールのパラメーターはプログラムによって設定することもできます。 現在の例を完了するには、指定したカテゴリに属するすべての製品を返す SqlDataSource が必要です。 この SqlDataSource の CategoryID パラメーターの値は、Page_Load イベント ハンドラーで RandomCategoryDataSource SqlDataSource によって返される CategoryID 列の値に基づいて設定する必要があります。

まず、ページに GridView を追加し、ProductsByCategoryDataSource という名前の新しい SqlDataSource にバインドします。 ステップ 3 で行ったように、GetProductsByCategory ストアド プロシージャを呼び出すように SqlDataSource を構成します。 [パラメーター ソース] ドロップダウン リストは [なし] のままにしますが、この既定値はプログラムによって設定されるため、既定値は入力しません。

Screenshot showing the Configure Data Source window with the Parameter source set to None.

図 14: パラメーター ソースまたは既定値を指定しない (クリックするとフルサイズの画像が表示されます)

SqlDataSource ウィザードを完了すると、結果の宣言型マークアップは次のようになります。

<asp:SqlDataSource ID="ProductsByCategoryDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="GetProductsByCategory" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter Name="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:SqlDataSource>

CategoryID パラメーターの DefaultValue は、Page_Load イベント ハンドラーでプログラムによって割り当てることができます。

' Assign the ProductsByCategoryDataSource's
' CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters("CategoryID").DefaultValue = _
    randomCategoryView(0)("CategoryID").ToString()

これを追加すると、ページには、ランダムに選ばれたカテゴリに関連付けられた製品を表示する GridView が含まれるようになります。

Screenshot showing the Your Randomly Selected Category page.

図 15: パラメーター ソースまたは既定値を指定しない (クリックするとフルサイズの画像が表示されます)

まとめ

SqlDataSource を使うと、ページ開発者は、パラメーター化されたクエリを定義し、パラメーターの値をハードコーディングしたり、定義済みのパラメーター ソースからプルしたり、プログラムで割り当てたりできます。 このチュートリアルでは、アドホック SQL クエリとストアド プロシージャの両方について、データ ソースの構成ウィザードからパラメーター化されたクエリを作成する方法について説明しました。 また、ハードコーディングされたパラメーター ソースの使用、パラメーター ソースとしての Web コントロール、プログラムによるパラメーター値の指定についても説明しました。

ObjectDataSource の場合と同様に、SqlDataSource には基になるデータを変更する機能も用意されています。 次のチュートリアルでは、SqlDataSource で INSERTUPDATEDELETE ステートメントを定義する方法について説明します。 これらのステートメントを追加すると、GridView、DetailsView、FormView コントロールに固有の、組み込みの挿入、編集、削除機能を利用できます。

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Scott Clyde、Randell Schmidt、Ken Pespisa でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。