次の方法で共有


その他の DataTable 列を追加する (VB)

スコット・ミッチェル著

PDF をダウンロードする

TableAdapter ウィザードを使用して型指定された DataSet を作成する場合、対応する DataTable には、メイン データベース クエリによって返される列が含まれます。 ただし、DataTable に追加の列を含める必要がある場合があります。 このチュートリアルでは、追加の DataTable 列が必要な場合にストアド プロシージャが推奨される理由について説明します。

イントロダクション

型指定された DataSet に TableAdapter を追加する場合、対応する DataTable のスキーマは TableAdapter のメイン クエリによって決定されます。 たとえば、メイン クエリがデータ フィールド ABC を返す場合、DataTable には ABC という名前の 3 つの対応する列があります。TableAdapter には、メイン クエリに加えて、何らかのパラメーターに基づいてデータのサブセットを返す追加のクエリを含めることができます。 たとえば、すべての製品に関する情報を返す ProductsTableAdapter のメイン クエリに加えて、指定されたパラメーターに基づいて特定の製品情報を返す GetProductsByCategoryID(categoryID)GetProductByProductID(productID)などのメソッドも含まれています。

DataTable のスキーマに TableAdapter のメイン クエリを反映するモデルは、すべての TableAdapter メソッドがメイン クエリで指定されたデータ フィールドと同じまたは少ないデータ フィールドを返す場合に適切に機能します。 TableAdapter メソッドが追加のデータ フィールドを返す必要がある場合は、それに応じて DataTable のスキーマを展開する必要があります。 マスター/詳細データ リストでマスター レコードの箇条書きリストを使用するチュートリアルでは、メイン クエリで定義されているCategoriesTableAdapterCategoryID、およびCategoryNameデータ フィールドとDescriptionを返すメソッドをNumberOfProductsに追加しました。このフィールドには、各カテゴリに関連付けられている製品の数を報告する追加のデータ フィールドが追加されました。 この新しいメソッドからCategoriesDataTableデータ フィールドの値をキャプチャするために、NumberOfProductsに新しい列を手動で追加しました。

ファイルのアップロードに関するチュートリアルで説明したように、アドホック SQL ステートメントを使用し、データ フィールドがメイン クエリと正確に一致しないメソッドを持つ TableAdapters には細心の注意を払う必要があります。 TableAdapter 構成ウィザードを再実行すると、データ フィールド リストがメイン クエリと一致するように、TableAdapter のすべてのメソッドが更新されます。 そのため、カスタマイズされた列リストを持つメソッドは、メイン クエリの列リストに戻り、期待されるデータは返されません。 この問題は、ストアド プロシージャを使用する場合には発生しません。

このチュートリアルでは、DataTable のスキーマを拡張して追加の列を含める方法について説明します。 アドホック SQL ステートメントを使用する場合の TableAdapter の脆弱性のため、このチュートリアルではストアド プロシージャを使用します。 ストアド プロシージャを使用するように TableAdapter を構成する方法の詳細については、型指定データセットの TableAdapter 用の新しいストアドプロシージャの作成既存のストアドプロシージャの使用に関するチュートリアルを参照してください。

手順 1: PriceQuartile列をProductsDataTableに追加する

Typed DataSet s TableAdapters の新しいストアド プロシージャの作成に関するチュートリアルでは、NorthwindWithSprocsという名前の型指定された DataSet を作成しました。 現在、この DataSet には、 ProductsDataTableEmployeesDataTable の 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を右クリックします。 コンテキスト メニューから [追加] を選択し、[列] を選択します。

ProductsDataTable に新しい列を追加する

図 1: ProductsDataTable に新しい列を追加する (フルサイズの画像を表示する をクリックします)

これにより、 System.String型の Column1 という名前の DataTable に新しい列が追加されます。 この列の名前を PriceQuartile に更新し、その型を System.Int32 する必要があります。これは、1 から 4 までの数値を保持するために使用されるためです。 ProductsDataTableで新しく追加した列を選択し、[プロパティ] ウィンドウで Name プロパティを PriceQuartile に、DataType プロパティを System.Int32 に設定します。

新しい列の名前と DataType プロパティを設定する

図 2: 新しい列の NameDataType のプロパティを設定します (フルサイズの画像を表示する をクリックします)。

図 2 に示すように、列の値を一意にする必要があるかどうか、列が自動インクリメント列の場合、データベースの NULL 値が許可されるかどうかなど、追加のプロパティを設定できます。 これらの値は既定値のままにします。

手順 2: GetProductsWithPriceQuartileMethod の作成

ProductsDataTable列を含むようにPriceQuartileが更新されたので、GetProductsWithPriceQuartile メソッドを作成する準備ができました。 まず、TableAdapter を右クリックし、コンテキスト メニューから [クエリの追加] を選択します。 これにより、TableAdapter クエリ構成ウィザードが起動します。このウィザードでは、最初にアドホック SQL ステートメントを使用するか、新規または既存のストアド プロシージャを使用するかを確認するプロンプトが表示されます。 価格四分位データを返すストアド プロシージャがまだないため、TableAdapter でこのストアド プロシージャを作成できるようにしましょう。 [新しいストアド プロシージャの作成] オプションを選択し、[次へ] をクリックします。

ストアド プロシージャを作成するように TableAdapter ウィザードに指示する

図 3: ストアド プロシージャを作成するように TableAdapter ウィザードに指示します (フルサイズの画像を表示する をクリックします)。

図 4 に示す後続の画面では、追加するクエリの種類を確認するメッセージが表示されます。 GetProductsWithPriceQuartile メソッドは、Products テーブルからすべての列とレコードを返すので、行を返す SELECT オプションを選択し、[次へ] をクリックします。

クエリは、複数の行を返す 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 名前を付け、[次へ] をクリックします。

ストアド プロシージャにProducts_SelectWithPriceQuartileの名前を付けます

図 5: ストアド プロシージャの Products_SelectWithPriceQuartile に名前を付ける (フルサイズの画像を表示する] をクリックします)

最後に、TableAdapter メソッドに名前を付けるメッセージが表示されます。 [データ テーブルの塗りつぶし] と [DataTable を返す] の両方のチェック ボックスをオンのままにし、メソッドに FillWithPriceQuartileGetProductsWithPriceQuartileの名前を付けます。

TableAdapter のメソッドに名前を付け、[完了] をクリックします

図 6: TableAdapter のメソッドに名前を付け、[完了] をクリックします (フルサイズの画像を表示する をクリックします)。

SELECT クエリを指定し、ストアド プロシージャと TableAdapter メソッドに名前を付けて、[完了] をクリックしてウィザードを完了します。 この時点で、ウィザードから、 OVER SQL コンストラクトまたはステートメントがサポートされていないことを示す警告が表示されることがあります。 これらの警告は無視できます。

ウィザードが完了したら、TableAdapter に FillWithPriceQuartile メソッドと GetProductsWithPriceQuartile メソッドが含まれている必要があり、データベースには Products_SelectWithPriceQuartile という名前のストアド プロシージャが含まれている必要があります。 TableAdapter にこの新しいメソッドが実際に含まれていることと、ストアド プロシージャがデータベースに正しく追加されたことを確認します。 データベースをチェックするときに、ストアド プロシージャが表示されない場合は、[ストアド プロシージャ] フォルダーを右クリックし、[最新の情報に更新] を選択してみてください。

TableAdapter に新しいメソッドが追加されたことを確認する

図 7: TableAdapter に新しいメソッドが追加されたことを確認する

データベースに Products_SelectWithPriceQuartile ストアド プロシージャが含まれていることを確認する

図 8: データベースに Products_SelectWithPriceQuartile ストアド プロシージャが含まれていることを確認する (フルサイズの画像を表示する をクリックします)

アドホック SQL ステートメントの代わりにストアド プロシージャを使用する利点の 1 つは、TableAdapter 構成ウィザードを再実行すると、ストアド プロシージャの列リストが変更されないことです。 TableAdapter を右クリックし、コンテキスト メニューから [構成] オプションを選択してウィザードを開始し、[完了] をクリックして完了します。 次に、データベースに移動し、 Products_SelectWithPriceQuartile ストアド プロシージャを表示します。 列リストが変更されていないことに注意してください。 アドホック SQL ステートメントを使用していた場合、TableAdapter 構成ウィザードを再実行すると、このクエリの列リストがメイン クエリ列リストと一致するように元に戻され、 GetProductsWithPriceQuartile メソッドで使用されるクエリから NTILE ステートメントが削除されます。

Data Access Layer の GetProductsWithPriceQuartile メソッドが呼び出されると、TableAdapter は Products_SelectWithPriceQuartile ストアド プロシージャを実行し、返された各レコードの ProductsDataTable に行を追加します。 ストアド プロシージャによって返されるデータ フィールドは、 ProductsDataTable の列にマップされます。 ストアド プロシージャから返される PriceQuartile データ フィールドがあるため、その値は ProductsDataTablePriceQuartile 列に割り当てられます。

クエリが PriceQuartile データ フィールドを返さない TableAdapter メソッドの場合、 PriceQuartile 列の値は、 DefaultValue プロパティで指定された値です。 図 2 に示すように、この値は既定値の DBNull に設定されています。 別の既定値を使用する場合は、それに応じて DefaultValue プロパティを設定します。 列DefaultValueに対してDataTypeの値が有効であることを確認してください(つまり、列System.Int32PriceQuartile)。

この時点で、DataTable に列を追加するために必要な手順を実行しました。 この追加の列が期待どおりに動作することを確認するには、各製品名、価格、価格の四分位数を表示する ASP.NET ページを作成します。 ただし、その前に、DAL の GetProductsWithPriceQuartile メソッドを呼び出すメソッドを含むようにビジネス ロジックレイヤーを更新する必要があります。 次に、手順 3 で BLL を更新し、手順 4 で ASP.NET ページを作成します。

手順 3: ビジネス ロジック レイヤーの拡張

プレゼンテーションレイヤーから新しい GetProductsWithPriceQuartile メソッドを使用する前に、まず対応するメソッドを BLL に追加する必要があります。 ProductsBLLWithSprocs クラス ファイルを開き、次のコードを追加します。

<System.ComponentModel.DataObjectMethodAttribute_
    (System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductsWithPriceQuartile() As NorthwindWithSprocs.ProductsDataTable
    Return Adapter.GetProductsWithPriceQuartile()
End Function

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] タブのドロップダウン リストを [なし] に設定します。

ProductsBLLWithSprocs クラスを使用するように ObjectDataSource を構成する

図 9: ProductsBLLWithSprocs クラスを使うように ObjectDataSource を構成する (クリックするとフルサイズの画像が表示されます)

GetProductsWithPriceQuartile メソッドから製品情報を取得する

図 10: GetProductsWithPriceQuartile メソッドから製品情報を取得します (フルサイズの画像を表示する をクリックします)。

データ ソースの構成ウィザードが完了すると、Visual Studio は、メソッドによって返される各データ フィールドの BoundField または CheckBoxField を GridView に自動的に追加します。 これらのデータ フィールドの 1 つが PriceQuartileです。これは、手順 1 で ProductsDataTable に追加した列です。

GridView のフィールドを編集し、 ProductNameUnitPrice、および 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 は、 InsertCommandUpdateCommand、および 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にメッセージを送ってください。