Share via


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

作成者: Scott Mitchell

PDF のダウンロード

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

はじめに

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

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

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

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

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

型指定 された DataSet の TableAdapters の新しいストアド プロシージャの作成に関 するチュートリアルでは、 という名前 NorthwindWithSprocsの型指定された DataSet を作成しました。 この DataSet には、現在、2 つの DataTable と が ProductsDataTableEmployeesDataTable含まれています。 には ProductsTableAdapter 、次の 3 つの方法があります。

  • GetProducts- テーブルからProductsすべてのレコードを返すメイン クエリ
  • GetProductsByCategoryID(categoryID) - 指定した categoryID を持つすべての製品を返します。
  • GetProductByProductID(productID) - 指定した productID を持つ特定の製品を返します。

メイン クエリと 2 つの追加メソッドはすべて、同じデータ フィールドのセット (つまり、テーブルのすべての列) をProducts返します。 関連付けられたサブクエリや、 テーブルまたは JOIN テーブルから関連データをCategoriesSuppliersプルするサブクエリはありません。 したがって、 ProductsDataTable にはテーブル内の各フィールドに対応する列があります Products

このチュートリアルでは、すべての製品を返す メソッドを ProductsTableAdapter 名前付き GetProductsWithPriceQuartile に追加します。 標準の製品データ フィールドに加えて、 GetProductsWithPriceQuartile 製品の価格が下がる四分位数を示すデータ フィールドも含まれます PriceQuartile 。 たとえば、価格が最も高い 25% の製品の値は PriceQuartile 1 になり、価格が下位 25% に下がる製品の値は 4 になります。 ただし、この情報を返すストアド プロシージャを作成する前に、 メソッドを使用するときに結果を保持PriceQuartileする列を含むように を更新ProductsDataTableするGetProductsWithPriceQuartile必要があります。

DataSet を NorthwindWithSprocs 開き、 を ProductsDataTable右クリックします。 コンテキスト メニューから [追加] を選択し、[列] を選択します。

ProductsDataTable に新しい列を追加する

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

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

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

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

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

手順 2: メソッドのGetProductsWithPriceQuartile作成

列を 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

上記のクエリでは、2005 年SQL Server新しいNTILE関数を使用して結果を 4 つのグループに分割します。このグループは、降順で並べ替えられた値によってUnitPrice決定されます。

残念ながら、クエリ ビルダーはキーワード (keyword)を解析する方法をOVER知らず、上記のクエリを解析するとエラーが表示されます。 したがって、クエリ ビルダーを使用せずに、ウィザードのテキスト ボックスに上記のクエリを直接入力します。

注意

NTILE および SQL Server 2005 の他のランク付け関数の詳細については、「SQL Server 2005 オンライン ブック」の「ROW_NUMBER (Transact-SQL)」および「ランク付け関数」セクションを参照してください。

クエリを SELECT 入力して [次へ] をクリックすると、ウィザードは作成するストアド プロシージャの名前を指定するように求められます。 新しいストアド プロシージャ Products_SelectWithPriceQuartile に名前を付け、[次へ] をクリックします。

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

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

最後に、TableAdapter メソッドの名前を指定するように求められます。 [Fill a DataTable]\(データテーブルの塗りつぶし\) と [Return a DataTable]\(データテーブルを返す\) チェック ボックスの両方をオンのままにし、メソッドに と という名前を付GetProductsWithPriceQuartileけますFillWithPriceQuartile

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

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

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

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

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

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

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

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

注意

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

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

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

この時点で、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 をツールボックスからDesignerにドラッグし、そのプロパティを IDProducts設定します。 GridView のスマート タグから、 という名前 ProductsDataSourceの新しい ObjectDataSource にバインドします。 クラス s GetProductsWithPriceQuartile メソッドを使用するように ObjectDataSource をProductsBLLWithSprocs構成します。 これは読み取り専用グリッドであるため、UPDATE、INSERT、DELETE タブのドロップダウン リストを (None) に設定します。

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

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

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

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

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

GridView のフィールドを編集し、、UnitPrice、および BoundFields を除くProductNameすべてのフィールドをPriceQuartile削除します。 値を UnitPrice 通貨として書式設定し UnitPrice 、BoundFields と PriceQuartile BoundFields をそれぞれ右揃えと中央揃えにするように 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 に追加できます。 このチュートリアルでは、 (メソッドでのみ使用GetProductsWithPriceQuartileされる) 列にProductsDataTable列を追加PriceQuartileするのではなく、ストアド プロシージャをメイン クエリとして使用Products_SelectWithPriceQuartileする という名前ProductsWithPriceQuartileTableAdapterの DataSet に TableAdapter を追加できました。 ASP.NET 価格四分位数で製品情報を取得する必要があるページでは を ProductsWithPriceQuartileTableAdapter使用しますが、 を引き続き使用できなかったページは を ProductsTableAdapter使用します。

新しい TableAdapter を追加すると、DataTables は未学習のままであり、その列は TableAdapter のメソッドによって返されるデータ フィールドを正確にミラーします。 ただし、追加の TableAdapter では、反復的なタスクと機能が導入される可能性があります。 たとえば、列を表示PriceQuartileした ASP.NET ページでも、挿入、更新、削除のサポートを提供する必要がある場合は、 ProductsWithPriceQuartileTableAdapter で、UpdateCommand、および DeleteCommand プロパティをInsertCommand適切に構成する必要があります。 これらのプロパティは をミラーしますがProductsTableAdapter、この構成では追加の手順が導入されています。 さらに、 クラスと ProductsWithPriceQuartileTableAdapter クラスを使用して、データベースに製品を更新、削除、または追加する方法が ProductsTableAdapter 2 つあります。

このチュートリアルのダウンロードには、 ProductsWithPriceQuartileTableAdapter この代替アプローチを NorthwindWithSprocs 示す DataSet のクラスが含まれています。

まとめ

ほとんどのシナリオでは、TableAdapter 内のすべてのメソッドが同じデータ フィールドのセットを返しますが、特定のメソッドまたは 2 つのメソッドが追加のフィールドを返す必要がある場合があります。 たとえば、詳細データリストを使用したマスター レコードの箇条書きの使用に関するチュートリアルでは、メイン クエリのデータ フィールドに加えて、各カテゴリにCategoriesTableAdapter関連付けられている製品の数を報告するフィールドを返すメソッドを に追加しましたNumberOfProducts。 このチュートリアルでは、メイン クエリのデータ フィールドに加えて、フィールドを返した PriceQuartile にメソッドを追加する方法ProductsTableAdapterについて説明しました。 TableAdapter のメソッドによって返される追加のデータ フィールドをキャプチャするには、対応する列を DataTable に追加する必要があります。

DataTable に列を手動で追加する場合は、TableAdapter でストアド プロシージャを使用することをお勧めします。 TableAdapter がアドホック SQL ステートメントを使用する場合、TableAdapter 構成ウィザードが実行されるたびに、すべてのメソッド データ フィールド リストが、メイン クエリによって返されるデータ フィールドに戻ります。 この問題はストアド プロシージャには及ばないため、このチュートリアルで使用することをお勧めします。

プログラミングに満足!

著者について

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

特別な感謝

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