パラメーター化されたクエリと SqlDataSource を使用する (C#)
このチュートリアルでは、引き続き 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
ステートメントと INSERT
、UPDATE
、および DELETE
ステートメントの両方で、パラメーター化されたクエリがサポートされます。 さらに、パラメーター値は、クエリ文字列、セッション状態、ページ上のコントロールなどのさまざまなソースから自動的にプルしたり、プログラムによって割り当てたりすることができます。 このチュートリアルでは、パラメーター化されたクエリを定義する方法と、宣言とプログラムの両方によってパラメーター値を指定する方法について説明します。
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 コントロールをドラッグし、ID
を Products25BucksAndUnderDataSource
に設定します。 次に、コントロールのスマート タグの [データ ソースの構成] リンクをクリックします。 使用するデータベース (NORTHWINDConnectionString
) を選択し、[次へ] をクリックします。
手順 1: テーブルまたはビューから列を選択する場合の WHERE 句の追加
SqlDataSource コントロールを使用してデータベースから返すデータを選択する場合、データ ソースの構成ウィザードで既存のテーブルまたはビューから返す列を選択することができます (図 1 を参照)。 これにより、SQL SELECT
ステートメントが自動的にビルドされます。SQL ステートメントは、SqlDataSource の Select()
メソッドが呼び出された場合にデータベースに送信されます。 前のチュートリアルで行ったように、ドロップダウン リストから Products テーブルを選択し、ProductID
、ProductName
、および UnitPrice
列をチェックします。
図 1: テーブルまたはビューから返す列を選択する (クリックするとフルサイズの画像が表示されます)
SELECT
ステートメントに WHERE
句を含めるには、WHERE
ボタンをクリックします。そうすると、[WHERE
句の追加] ダイアログ ボックスが表示されます (図 2 を参照)。 SELECT
クエリによって返される結果を制限するパラメーターを追加するにはまず、データをフィルター処理する列を選択します。 次に、フィルター処理に使用する演算子 (=、<、<=、> など) を選択します。 最後に、クエリ文字列やセッション状態など、パラメーターの値のソースを選択します。 パラメーターを構成したら、[追加] ボタンをクリックして SELECT
クエリに含めます。
この例では、UnitPrice
の値が $25.00 以下の結果のみを返します。 したがって、[列] ドロップダウン リストから選択 UnitPrice
し、[演算子] ドロップダウン リストから <= を選択します。 ハードコーディングされたパラメーター値 ($25.00 など) を使用する場合や、パラメーター値をプログラムによって指定する場合は、[ソース] ドロップダウン リストから [なし] を選択します。 その後、[値] テキストボックスにハードコーディングされたパラメーター値 25.00 を入力し、[追加] ボタンをクリックしてプロセスを完了します。
図 2: [WHERE
句の追加] ダイアログ ボックスから返される結果を制限する (クリックするとフルサイズの画像が表示されます)
パラメーターを追加したら、[OK] をクリックしてデータ ソースの構成ウィザードに戻ります。 ウィザードの下部にある SELECT
ステートメントに、@UnitPrice
という名前のパラメーターを含む WHERE
句が含まれるようになりました。
SELECT [ProductID], [ProductName], [UnitPrice]
FROM [Products]
WHERE ([UnitPrice] <= @UnitPrice)
Note
[WHERE
句の追加] ダイアログ ボックスで WHERE
句に複数の条件を指定すると、ウィザードによって AND
演算子と結合されます。 WHERE
句 (WHERE UnitPrice <= @UnitPrice OR Discontinued = 1
など) に OR
を含める必要がある場合は、カスタム 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 ドル以下の製品のみが表示されます。
図 3: $25.00 以下の製品のみが表示される (クリックするとフルサイズの画像が表示されます)
手順 2: カスタム SQL ステートメントにパラメーターを追加する
カスタム SQL ステートメントを追加する場合は、WHERE
句を明示的に入力するか、クエリ ビルダーの [フィルター] セルに値を指定することができます。 これを示すために、価格が特定のしきい値より小さい製品だけを GridView に表示してみましょう。 まず、TextBox を ParameterizedQueries.aspx
ページに追加して、ユーザーからこのしきい値を収集します。 TextBox の ID
プロパティを MaxPrice
に設定します。 ボタン Web コントロールを追加し、その Text
プロパティを [一致する製品の表示] に設定します。
次に、GridView をページにドラッグし、そのスマート タグから ProductsFilteredByPriceDataSource
という名前の新しい SqlDataSource を選択して作成します。 データ ソースの構成ウィザードから、[カスタム SQL ステートメントまたはストアド プロシージャの指定] 画面 (図 4 を参照) に進み、次のクエリを入力します。
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice <= @MaximumPrice
(手動またはクエリ ビルダーを使用して) クエリを入力した後、[次へ] をクリックします。
図 4: パラメーター値以下の製品のみが返される (クリックするとフルサイズの画像が表示されます)
クエリにはパラメーターが含まれるため、ウィザードの次の画面でパラメーター値のソースの入力を求められます。 [パラメーター ソース] ドロップダウン リストから [コントロール] を選択し、[ControlID] ドロップダウン リストから MaxPrice
(TextBox コントロールの ID
値) を選択します。 ユーザーが MaxPrice
TextBox にテキストを入力していない場合に使用する省略可能な既定値を入力することもできます。 当面は、既定値を入力しないでください。
図 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>
セクション内のパラメーターは、ControlID
や PropertyName
のような追加のプロパティを含む ControlParameter
であることに注意してください。 SqlDataSource の Select()
メソッドが呼び出されると、ControlParameter
は指定した Web コントロール プロパティから値を取得し、SelectCommand
内の対応するパラメーターに割り当てます。 この例では、MaxPrice
の Text プロパティが @MaxPrice
パラメーター値として使用されます。
ブラウザーでこのページを表示するには、少し時間がかかります。 最初にページにアクセスした場合や、TextBox に MaxPrice
値がない場合は常に、GridView にレコードが表示されません。
図 6: MaxPrice
TextBox が空の場合、レコードは表示されない (クリックするとフルサイズの画像が表示されます)
製品が表示されないのは、パラメーター値の空の文字列が既定でデータベースの NULL
値に変換されるためです。 [UnitPrice] <= NULL
の比較は常に False と評価されるため、結果は返されません。
テキストボックスに値 (5.00 など) を入力し、[一致する製品の表示] ボタンをクリックします。 ポストバック時に、SqlDataSource はパラメーター ソースの 1 つが変更されたことを GridView に通知します。 その結果、GridView が SqlDataSource に再バインドされ、$5.00 以下の製品が表示されます。
図 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
の値に設定され、すべての製品が表示されます。
図 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.0
を WHERE
句に追加すると、クエリ エンジンは 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: 1 の @CategoryID
で実行された GetProductsByCategory
ストアド プロシージャ (クリックするとフルサイズの画像が表示されます)
このストアド プロシージャを使用して、GridView の [飲料] カテゴリのすべての製品を表示してみましょう。 ページに新しい GridView を追加し、BeverageProductsDataSource
という名前の新しい SqlDataSource にバインドします。 [カスタム SQL ステートメントまたはストアド プロシージャの指定] 画面に進み、[ストアド プロシージャ] ラジオ ボタンを選択し、ドロップダウン リストから GetProductsByCategory
ストアド プロシージャを選択します。
図 10: ドロップダウン リストから GetProductsByCategory
ストアド プロシージャを選択する (クリックするとフルサイズの画像が表示されます)
ストアド プロシージャは入力パラメーター (@CategoryID
) を受け入れるため、[次へ] をクリックすると、このパラメーターの値のソースを指定するように求められます。 飲料 CategoryID
は 1 なので、[パラメーター ソース] ドロップダウン リストは [なし] のままにし、[DefaultValue] ボックスに「1」と入力します。
図 11: ハードコーディングされた値 1 を使用して飲料カテゴリの製品を返す (クリックするとフルサイズの画像が表示されます)
次の宣言型マークアップが示すように、ストアド プロシージャを使用する場合、SqlDataSource の SelectCommand
プロパティはストアド プロシージャの名前に設定され、SelectCommandType
プロパティは SelectCommand
がアドホック SQL ステートメントではなくストアド プロシージャの名前であることを示す StoredProcedure
に設定されます。
<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 の作成について説明します。
まず、ParameterizedQueries.aspx
に SqlDataSource を追加し、その ID
を RandomCategoryDataSource
に設定します。 次の SQL クエリを使用するように構成します。
SELECT TOP 1 CategoryID, CategoryName
FROM Categories
ORDER BY NEWID()
ORDER BY NEWID()
は、ランダムな順序で並べ替えられたレコードを返します (「NEWID()
をレコードのランダムな並べ替えに使用する」を参照)。 SELECT TOP 1
は、結果セットの最初のレコードを返します。 まとめると、このクエリは、ランダムに選択された 1 つのカテゴリの CategoryID
および CategoryName
列の値を返します。
カテゴリの CategoryName
値を表示するには、ラベル 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 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: ランダムに選択されたカテゴリの名前が表示される (クリックするとフルサイズの画像が表示されます)
Note
SqlDataSource コントロールの DataSourceMode
プロパティが DataReader
に設定されている場合は、Select()
メソッドからの戻り値を IDataReader
にキャストする必要がありました。 最初の行の CategoryName
列の値を読み取るために、次のようなコードを使用します。
if (randomCategoryReader.Read())
{
string categoryName = randomCategoryReader["CategoryName"].ToString();
...
}
SqlDataSource でカテゴリがランダムに選択され、カテゴリの製品を一覧表示する GridView を追加する準備ができました。
Note
ラベル Web コントロールを使用してカテゴリの名前を表示するのではなく、ページに FormView または DetailsView を追加して、SqlDataSource にバインドすることもできます。 ただし、Label を使用すると、SqlDataSource の Select()
ステートメントをプログラムによって呼び出し、その結果のデータをコードで操作する方法を調べることができます。
手順 5: プログラムによるパラメーター値の割り当て
このチュートリアルでこれまでに見てきたすべての例では、ハードコーディングされたパラメーター値または定義済みのパラメーター ソース (クエリ文字列値、ページ上の Web コントロールなど) から取得したパラメーター値を使用しています。 ただし、SqlDataSource コントロールのパラメーターはプログラムによって設定することもできます。 現在の例を完了するには、指定したカテゴリに属するすべての製品を返す SqlDataSource が必要です。 この SqlDataSource には、Page_Load
イベント ハンドラーで RandomCategoryDataSource
SqlDataSource によって返される CategoryID
列の値に基づいて値を設定する必要がある CategoryID
パラメーターがあります。
まず、ページに GridView を追加し、ProductsByCategoryDataSource
という名前の新しい SqlDataSource にバインドします。 手順 3 で行ったように、SqlDataSource を GetProductsByCategory
ストアド プロシージャを呼び出すように構成します。 この既定値はプログラムによって設定されるため、[パラメーター ソース] ドロップダウン リストは [なし] のままにし、既定値を入力しないでください。
図 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>
Page_Load
イベント ハンドラーでプログラムによって CategoryID
パラメーターの DefaultValue
を割り当てることができます。
// 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 を使用して INSERT
、UPDATE
、および DELETE
ステートメントを定義する方法について説明します。 これらのステートメントを追加した後、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行をドロップしてください。