次の方法で共有


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

スコット・ミッチェル著

PDF をダウンロードする

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

イントロダクション

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

前のチュートリアルのデモで使用した 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 ステートメントの両方に対応しています。 さらに、パラメーター値は、クエリ文字列、セッション状態、ページ上のコントロールなどのさまざまなソースから自動的にプルしたり、プログラムで割り当てたりすることができます。 このチュートリアルでは、パラメーター化されたクエリを定義する方法と、宣言型とプログラム型の両方でパラメーター値を指定する方法について説明します。

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

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

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

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

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

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

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

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

テーブルまたはビューから返す列を選ぶ

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

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

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

[WHERE 句の追加] ダイアログ ボックスから返される結果を制限する

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

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

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

[WHERE句の追加] ダイアログ ボックスで WHERE 句に複数の条件を指定した場合、ウィザードはそれらを AND 演算子と結合します。 OR句 (WHERE など) に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() メソッドが呼び出されると、データベースに送信される前に、UnitPrice パラメーター値 (25.00) が@UnitPriceSelectCommand パラメーターに適用されます。 結果として、 Products テーブルから返されるのは 25.00 ドル以下の製品だけです。 これを確認するには、ページに GridView を追加し、このデータ ソースにバインドしてから、ブラウザーを使用してページを表示します。 図 3 に示すように、25.00 ドル以下の製品のみが表示されます。

$25.00 以下の製品のみが表示されます

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

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

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

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

SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice

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

パラメーター値以下の製品のみを返します

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

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

MaxPrice TextBox の Text プロパティがパラメーター ソースとして使用される

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

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

MaxPrice TextBox が空の場合、レコードは表示されません

図 6: MaxPrice テキスト ボックスが空の場合、レコードは表示されません (フルサイズの画像を表示する をクリックします)。

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

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

$5.00 以下の製品が表示されます

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

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

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

前のチュートリアル - 宣言型パラメーター、DropDownList を使用したマスター/詳細フィルター処理 でも、同様の問題が発生しました。 ソリューションでは、このロジックをビジネス ロジック レイヤーに配置しました。 具体的には、BLL は受信値を調べ、 NULL または予約された値がある場合、呼び出しはすべてのレコードを返す DAL メソッドにルーティングされました。 受信値が通常のフィルター値の場合、指定された値でパラメーター化された WHERE 句を使用する SQL ステートメントを実行する DAL メソッドに対して呼び出しが行われました。

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

MaxPrice TextBox が空のときにすべての製品が表示されるようになりました

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

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

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

手順 3: パラメーター化ストアド プロシージャの作成と使用

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

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

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

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

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

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

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

Drop-Down リストから GetProductsByCategory ストアド プロシージャを選択します

図 10: Drop-Down の一覧から GetProductsByCategory ストアド プロシージャを選択します (フルサイズの画像を表示する をクリックします)。

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

Hard-Coded 値 1 を使用して、飲料カテゴリの製品を返します。

図 11: Hard-Coded 値 1 を使用して飲料カテゴリの製品を返す (フルサイズの画像を表示する をクリックします)。

次の宣言型マークアップが示すように、ストアド プロシージャを使用する場合、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>

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

すべての飲料が表示されます

図 12: すべての飲料が表示されます (フルサイズの画像を表示する をクリックします)。

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

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

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

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

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

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

ORDER BY NEWID() は、ランダムな順序で並べ替えられたレコードを返します ( NEWID() を使用してレコードをランダムに並べ替える」を参照)。 SELECT TOP 1 は、結果セットから最初のレコードを返します。 一緒に言えば、このクエリは、ランダムに選択された単一のカテゴリから CategoryIDCategoryName 列の値を返します。

カテゴリの 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 オブジェクトを操作します。

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

protected void Page_Load(object sender, EventArgs e)
{
    // Get the data from the SqlDataSource as a DataView
    DataView randomCategoryView =
        (DataView)RandomCategoryDataSource.Select(DataSourceSelectArguments.Empty);
    if (randomCategoryView.Count > 0)
    {
        // Assign the CategoryName value to the Label
        CategoryNameLabel.Text =
            string.Format("Here are Products in the {0} Category...",
                randomCategoryView[0]["CategoryName"].ToString());
    }
}

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

ランダムに選択されたカテゴリの名前が表示されます

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

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

if (randomCategoryReader.Read())
{
   string categoryName = randomCategoryReader["CategoryName"].ToString();
   ...
}

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

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

手順 5: プログラムによるパラメーター値の割り当て

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

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

[パラメーター ソース] が [なし] に設定されている [データ ソースの構成] ウィンドウを示すスクリーンショット。

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

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

// Assign the ProductsByCategoryDataSource's
// CategoryID parameter's DefaultValue property
ProductsByCategoryDataSource.SelectParameters["CategoryID"].DefaultValue =
    randomCategoryView[0]["CategoryID"].ToString();

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

[ランダムに選択されたカテゴリ] ページを示すスクリーンショット。

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

概要

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

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

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。

特別な感謝

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