TableAdapter ウィザードを使用して型指定された DataSet を作成する場合、対応する DataTable には、メイン データベース クエリによって返される列が含まれます。 ただし、DataTable に追加の列を含める必要がある場合があります。 このチュートリアルでは、追加の DataTable 列が必要な場合にストアド プロシージャが推奨される理由について説明します。
イントロダクション
型指定された DataSet に TableAdapter を追加する場合、対応する DataTable のスキーマは TableAdapter のメイン クエリによって決定されます。 たとえば、メイン クエリがデータ フィールド A、 B、 C を返す場合、DataTable には A、 B、 C という名前の 3 つの対応する列があります。TableAdapter には、メイン クエリに加えて、何らかのパラメーターに基づいてデータのサブセットを返す追加のクエリを含めることができます。 たとえば、すべての製品に関する情報を返す ProductsTableAdapter
のメイン クエリに加えて、指定されたパラメーターに基づいて特定の製品情報を返す GetProductsByCategoryID(categoryID)
や GetProductByProductID(productID)
などのメソッドも含まれています。
DataTable のスキーマに TableAdapter のメイン クエリを反映するモデルは、すべての TableAdapter メソッドがメイン クエリで指定されたデータ フィールドと同じまたは少ないデータ フィールドを返す場合に適切に機能します。 TableAdapter メソッドが追加のデータ フィールドを返す必要がある場合は、それに応じて DataTable のスキーマを展開する必要があります。 マスター/詳細データ リストでマスター レコードの箇条書きリストを使用するチュートリアルでは、メイン クエリで定義されているCategoriesTableAdapter
、CategoryID
、およびCategoryName
データ フィールドとDescription
を返すメソッドをNumberOfProducts
に追加しました。このフィールドには、各カテゴリに関連付けられている製品の数を報告する追加のデータ フィールドが追加されました。 この新しいメソッドからCategoriesDataTable
データ フィールドの値をキャプチャするために、NumberOfProducts
に新しい列を手動で追加しました。
ファイルのアップロードに関するチュートリアルで説明したように、アドホック SQL ステートメントを使用し、データ フィールドがメイン クエリと正確に一致しないメソッドを持つ TableAdapters には細心の注意を払う必要があります。 TableAdapter 構成ウィザードを再実行すると、データ フィールド リストがメイン クエリと一致するように、TableAdapter のすべてのメソッドが更新されます。 そのため、カスタマイズされた列リストを持つメソッドは、メイン クエリの列リストに戻り、期待されるデータは返されません。 この問題は、ストアド プロシージャを使用する場合には発生しません。
このチュートリアルでは、DataTable のスキーマを拡張して追加の列を含める方法について説明します。 アドホック SQL ステートメントを使用する場合の TableAdapter の脆弱性のため、このチュートリアルではストアド プロシージャを使用します。 ストアド プロシージャを使用するように TableAdapter を構成する方法の詳細については、 型指定されたデータセットの TableAdapters のチュートリアルの新規ストアド プロシージャの作成 を参照してください。
手順 1: PriceQuartile
列をProductsDataTable
に追加する
Typed DataSet s TableAdapters の新しいストアド プロシージャの作成に関するチュートリアルでは、NorthwindWithSprocs
という名前の型指定された DataSet を作成しました。 現在、この DataSet には、 ProductsDataTable
と EmployeesDataTable
の 2 つの DataTable が含まれています。
ProductsTableAdapter
には、次の 3 つの方法があります。
-
GetProducts
-Products
テーブルからすべてのレコードを返すメイン クエリ -
GetProductsByCategoryID(categoryID)
- 指定した categoryID を持つすべての製品を返します。 -
GetProductByProductID(productID)
- 指定した productID を持つ特定の製品を返します。
メイン クエリと 2 つの追加メソッドはすべて、同じデータ フィールドのセット、つまり、 Products
テーブルのすべての列を返します。
JOIN
テーブルまたはCategories
テーブルから関連するデータをプルする関連サブクエリやSuppliers
はありません。 そのため、 ProductsDataTable
には、 Products
テーブルの各フィールドに対応する列があります。
このチュートリアルでは、すべての製品を返す ProductsTableAdapter
という名前のGetProductsWithPriceQuartile
にメソッドを追加します。 標準の製品データ フィールドに加えて、 GetProductsWithPriceQuartile
には、製品の価格が下がる四分位数を示す PriceQuartile
データ フィールドも含まれます。 たとえば、価格が最も高価な 25% の製品の PriceQuartile
値は 1 になり、価格が下位 25% に下がる製品の値は 4 になります。 ただし、この情報を返すストアド プロシージャの作成を心配する前に、ProductsDataTable
メソッドを使用するときにPriceQuartile
結果を保持する列を含むようにGetProductsWithPriceQuartile
を更新する必要があります。
NorthwindWithSprocs
DataSet を開き、ProductsDataTable
を右クリックします。 コンテキスト メニューから [追加] を選択し、[列] を選択します。
図 1: ProductsDataTable
に新しい列を追加する (フルサイズの画像を表示する をクリックします)
これにより、 System.String
型の Column1 という名前の DataTable に新しい列が追加されます。 この列の名前を PriceQuartile に更新し、その型を System.Int32
する必要があります。これは、1 から 4 までの数値を保持するために使用されるためです。
ProductsDataTable
で新しく追加した列を選択し、[プロパティ] ウィンドウで Name
プロパティを PriceQuartile に、DataType
プロパティを System.Int32
に設定します。
図 2: 新しい列の Name
と DataType
のプロパティを設定します (フルサイズの画像を表示する をクリックします)。
図 2 に示すように、列の値を一意にする必要があるかどうか、列が自動インクリメント列の場合、データベースの NULL
値が許可されるかどうかなど、追加のプロパティを設定できます。 これらの値は既定値のままにします。
手順 2: GetProductsWithPriceQuartile
Method の作成
ProductsDataTable
列を含むようにPriceQuartile
が更新されたので、GetProductsWithPriceQuartile
メソッドを作成する準備ができました。 まず、TableAdapter を右クリックし、コンテキスト メニューから [クエリの追加] を選択します。 これにより、TableAdapter クエリ構成ウィザードが起動します。このウィザードでは、最初にアドホック SQL ステートメントを使用するか、新規または既存のストアド プロシージャを使用するかを確認するプロンプトが表示されます。 価格四分位データを返すストアド プロシージャがまだないため、TableAdapter でこのストアド プロシージャを作成できるようにしましょう。 [新しいストアド プロシージャの作成] オプションを選択し、[次へ] をクリックします。
図 3: ストアド プロシージャを作成するように TableAdapter ウィザードに指示します (フルサイズの画像を表示する をクリックします)。
図 4 に示す後続の画面では、追加するクエリの種類を確認するメッセージが表示されます。
GetProductsWithPriceQuartile
メソッドは、Products
テーブルからすべての列とレコードを返すので、行を返す SELECT オプションを選択し、[次へ] をクリックします。
図 4: クエリは、複数の行を返す SELECT
ステートメントになります (フルサイズの画像を表示する をクリックします)。
次に、 SELECT
クエリの入力を求められます。 ウィザードに次のクエリを入力します。
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued,
NTILE(4) OVER (ORDER BY UnitPrice DESC) as PriceQuartile
FROM Products
上記のクエリでは、SQL Server 2005 の新しい NTILE
関数 を使用して結果を 4 つのグループに分割し、グループは降順に並べ替えられた UnitPrice
値によって決定されます。
残念ながら、クエリ ビルダーは OVER
キーワードを解析する方法を知らず、上記のクエリを解析するときにエラーが表示されます。 したがって、クエリ ビルダーを使用せずに、ウィザードのテキスト ボックスに上記のクエリを直接入力します。
注
NTILE および SQL Server 2005 の他のランク付け関数の詳細については、SQL Server 2005 オンライン ブックの「ROW_NUMBER (Transact-SQL)」および「ランク付け関数」セクションを参照してください。
SELECT
クエリを入力し、[次へ] をクリックすると、ウィザードによって、作成するストアド プロシージャの名前を指定するように求められます。 新しいストアド プロシージャに Products_SelectWithPriceQuartile
名前を付け、[次へ] をクリックします。
図 5: ストアド プロシージャの Products_SelectWithPriceQuartile
に名前を付ける (フルサイズの画像を表示する] をクリックします)
最後に、TableAdapter メソッドに名前を付けるメッセージが表示されます。 [データ テーブルの塗りつぶし] と [DataTable を返す] の両方のチェック ボックスをオンのままにし、メソッドに FillWithPriceQuartile
と GetProductsWithPriceQuartile
の名前を付けます。
図 6: TableAdapter のメソッドに名前を付け、[完了] をクリックします (フルサイズの画像を表示する をクリックします)。
SELECT
クエリを指定し、ストアド プロシージャと TableAdapter メソッドに名前を付けて、[完了] をクリックしてウィザードを完了します。 この時点で、ウィザードから、 OVER
SQL コンストラクトまたはステートメントがサポートされていないことを示す警告が表示されることがあります。 これらの警告は無視できます。
ウィザードが完了したら、TableAdapter に FillWithPriceQuartile
メソッドと GetProductsWithPriceQuartile
メソッドが含まれている必要があり、データベースには Products_SelectWithPriceQuartile
という名前のストアド プロシージャが含まれている必要があります。 TableAdapter にこの新しいメソッドが実際に含まれていることと、ストアド プロシージャがデータベースに正しく追加されたことを確認します。 データベースをチェックするときに、ストアド プロシージャが表示されない場合は、[ストアド プロシージャ] フォルダーを右クリックし、[最新の情報に更新] を選択してみてください。
図 7: TableAdapter に新しいメソッドが追加されたことを確認する
図 8: データベースに Products_SelectWithPriceQuartile
ストアド プロシージャが含まれていることを確認する (フルサイズの画像を表示する をクリックします)
注
アドホック SQL ステートメントの代わりにストアド プロシージャを使用する利点の 1 つは、TableAdapter 構成ウィザードを再実行すると、ストアド プロシージャの列リストが変更されないことです。 TableAdapter を右クリックし、コンテキスト メニューから [構成] オプションを選択してウィザードを開始し、[完了] をクリックして完了します。 次に、データベースに移動し、 Products_SelectWithPriceQuartile
ストアド プロシージャを表示します。 列リストが変更されていないことに注意してください。 アドホック SQL ステートメントを使用していた場合、TableAdapter 構成ウィザードを再実行すると、このクエリの列リストがメイン クエリ列リストと一致するように元に戻され、 GetProductsWithPriceQuartile
メソッドで使用されるクエリから NTILE ステートメントが削除されます。
Data Access Layer の GetProductsWithPriceQuartile
メソッドが呼び出されると、TableAdapter は Products_SelectWithPriceQuartile
ストアド プロシージャを実行し、返された各レコードの ProductsDataTable
に行を追加します。 ストアド プロシージャによって返されるデータ フィールドは、 ProductsDataTable
の列にマップされます。 ストアド プロシージャから返される PriceQuartile
データ フィールドがあるため、その値は ProductsDataTable
の PriceQuartile
列に割り当てられます。
クエリが PriceQuartile
データ フィールドを返さない TableAdapter メソッドの場合、 PriceQuartile
列の値は、 DefaultValue
プロパティで指定された値です。 図 2 に示すように、この値は既定値の DBNull
に設定されています。 別の既定値を使用する場合は、それに応じて DefaultValue
プロパティを設定します。 列DefaultValue
に対してDataType
の値が有効であることを確認してください(つまり、列System.Int32
のPriceQuartile
)。
この時点で、DataTable に列を追加するために必要な手順を実行しました。 この追加の列が期待どおりに動作することを確認するには、各製品名、価格、価格の四分位数を表示する ASP.NET ページを作成します。 ただし、その前に、DAL の GetProductsWithPriceQuartile
メソッドを呼び出すメソッドを含むようにビジネス ロジックレイヤーを更新する必要があります。 次に、手順 3 で BLL を更新し、手順 4 で ASP.NET ページを作成します。
手順 3: ビジネス ロジック レイヤーの拡張
プレゼンテーションレイヤーから新しい GetProductsWithPriceQuartile
メソッドを使用する前に、まず対応するメソッドを BLL に追加する必要があります。
ProductsBLLWithSprocs
クラス ファイルを開き、次のコードを追加します。
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable GetProductsWithPriceQuartile()
{
return Adapter.GetProductsWithPriceQuartile();
}
ProductsBLLWithSprocs
の他のデータ取得メソッドと同様に、GetProductsWithPriceQuartile
メソッドは DAL の対応する GetProductsWithPriceQuartile
メソッドを呼び出し、その結果を返します。
手順 4: ASP.NET Web ページに価格四分位数情報を表示する
BLL の追加が完了したら、各製品の価格四分位数を示す ASP.NET ページを作成する準備ができました。
AddingColumns.aspx
フォルダーのAdvancedDAL
ページを開き、ツールボックスからデザイナーに GridView をドラッグし、そのID
プロパティをProducts
に設定します。 GridView のスマート タグから、 ProductsDataSource
という名前の新しい ObjectDataSource にバインドします。
ProductsBLLWithSprocs
クラスの GetProductsWithPriceQuartile
メソッドを使用するように ObjectDataSource を構成します。 これは読み取り専用グリッドであるため、[UPDATE]、[INSERT]、[DELETE] タブのドロップダウン リストを [なし] に設定します。
図 9: ProductsBLLWithSprocs
クラスを使うように ObjectDataSource を構成する (クリックするとフルサイズの画像が表示されます)
図 10: GetProductsWithPriceQuartile
メソッドから製品情報を取得します (フルサイズの画像を表示する をクリックします)。
データ ソースの構成ウィザードが完了すると、Visual Studio は、メソッドによって返される各データ フィールドの BoundField または CheckBoxField を GridView に自動的に追加します。 これらのデータ フィールドの 1 つが PriceQuartile
です。これは、手順 1 で ProductsDataTable
に追加した列です。
GridView のフィールドを編集し、 ProductName
、 UnitPrice
、および BoundFields を除くすべてのフィールド PriceQuartile
削除します。
UnitPrice
BoundField を構成して、その値を通貨として書式設定し、UnitPrice
BoundField を右揃えに、PriceQuartile
BoundField を中央揃えにします。 最後に、残りの BoundFields HeaderText
プロパティをそれぞれ Product、Price、Price Quartile に更新します。 また、GridView のスマート タグから [並べ替えを有効にする] チェック ボックスをオンにします。
これらの変更の後、GridView と ObjectDataSource の宣言型マークアップは次のようになります。
<asp:GridView ID="Products" runat="server" AllowSorting="True"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="PriceQuartile" HeaderText="Price Quartile"
SortExpression="PriceQuartile">
<ItemStyle HorizontalAlign="Center" />
</asp:BoundField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsWithPriceQuartile"
TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>
図 11 は、ブラウザーからアクセスした場合のこのページを示しています。 最初に、製品の価格が降順で並べ替えられ、その後、各製品に適切な PriceQuartile
値が割り当てられます。 もちろん、このデータは、価格に関する製品のランキングを反映した価格四分位数列の値を持つ他の基準で並べ替えることができます (図 12 を参照)。
図 11: 製品は価格順に並べ替えられます (フルサイズの画像を表示する をクリックします)
図 12: 製品は名前で並べ替えられます (フルサイズの画像を表示する をクリックします)
注
数行のコードを使用すると、GridView を拡張して、 PriceQuartile
値に基づいて製品行に色を付けることができました。 製品を最初の四分位数では薄い緑色に色を付け、2 番目の四分位数では薄い黄色に色を付ける、といった具合にするかもしれません。 この機能を追加する時間を取ることをお勧めします。 GridView の書式設定に関する更新プログラムが必要な場合は、「 データに基づくカスタム書式設定」チュートリアルを 参照してください。
別の方法 - 別の TableAdapter の作成
このチュートリアルで説明したように、メイン クエリによってスペルアウトされたデータ フィールド以外のデータ フィールドを返す TableAdapter にメソッドを追加するときに、対応する列を DataTable に追加できます。 ただし、このような方法は、異なるデータ フィールドを返すメソッドが TableAdapter に少数存在する場合や、それらの代替データ フィールドがメイン クエリとあまり異なっていない場合にのみ有効です。
DataTable に列を追加するのではなく、別のデータ フィールドを返す最初の TableAdapter のメソッドを含む別の TableAdapter を DataSet に追加できます。 このチュートリアルでは、PriceQuartile
列をProductsDataTable
に追加するのではなく (GetProductsWithPriceQuartile
メソッドでのみ使用されます)、ProductsWithPriceQuartileTableAdapter
ストアド プロシージャをメイン クエリとして使用する Products_SelectWithPriceQuartile
という名前の DataSet に TableAdapter を追加できました。 ASP.NET ページで、価格の四分位数を用いた製品情報が必要な場合はProductsWithPriceQuartileTableAdapter
を使用しますが、そうでない場合は引き続きProductsTableAdapter
を使用することができます。
新しい TableAdapter を追加すると、DataTable は汚されず、その列は TableAdapter のメソッドによって返されるデータフィールドを正確に反映します。 ただし、TableAdapter を追加すると、反復的なタスクと機能が導入される可能性があります。 たとえば、 PriceQuartile
列を表示した ASP.NET ページでも、挿入、更新、削除のサポートを提供する必要がある場合、 ProductsWithPriceQuartileTableAdapter
は、 InsertCommand
、 UpdateCommand
、および DeleteCommand
プロパティを適切に構成する必要があります。 これらのプロパティは ProductsTableAdapter
を反映しますが、この構成では追加の手順が導入されます。 さらに、 ProductsTableAdapter
クラスと ProductsWithPriceQuartileTableAdapter
クラスを使用して、データベースに製品を更新、削除、または追加する 2 つの方法があります。
このチュートリアルのダウンロードには、この代替方法を示す ProductsWithPriceQuartileTableAdapter
DataSet のNorthwindWithSprocs
クラスが含まれています。
概要
ほとんどのシナリオでは、TableAdapter のすべてのメソッドが同じデータ フィールドのセットを返しますが、特定のメソッドまたは 2 つのメソッドが追加のフィールドを返す必要がある場合があります。 たとえば、マスター/詳細データ リストを使用してマスター レコードの箇条書きを使用するチュートリアルでは、メイン クエリのデータ フィールドに加えて、各カテゴリに関連付けられている製品の数を報告するCategoriesTableAdapter
フィールドを返すメソッドをNumberOfProducts
に追加しました。 このチュートリアルでは、メイン クエリのデータ フィールドに加えて、ProductsTableAdapter
フィールドを返すメソッドをPriceQuartile
に追加する方法について説明しました。 TableAdapter メソッドによって返される追加のデータ フィールドをキャプチャするには、対応する列を DataTable に追加する必要があります。
DataTable に列を手動で追加する場合は、TableAdapter でストアド プロシージャを使用することをお勧めします。 TableAdapter でアドホック SQL ステートメントが使用されている場合、TableAdapter 構成ウィザードが実行されるたびに、すべてのメソッド データ フィールド リストがメイン クエリによって返されるデータ フィールドに戻ります。 この問題はストアド プロシージャには及ばないため、このチュートリアルで使用することをお勧めします。
プログラミングに満足!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Randy Schmidt、Jacky Goor、Bernadette Leigh、Hilton Giesenow でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにメッセージを送ってください。