Visual Studio のデータセットの概要

更新 : 2007 年 11 月

データセットは、アプリケーションで使用するためにデータを一時的に格納できるデータ テーブルを含むオブジェクトです。アプリケーションでデータを操作する必要がある場合、データをデータセットに読み込むことができ、それがアプリケーションで操作するデータのローカルのメモリ内キャッシュになります。データセット内のデータは、アプリケーションがデータベースから切断されても操作できます。データセットでは、データへの変更に関する情報が保持されるので、更新情報を追跡して、アプリケーションがデータベースに再度接続されたときにデータベースに更新情報を送信できます。

DataSet の構造はリレーショナル データベースに似ています。データセットは、テーブル、行、列、制約、およびリレーションシップの階層オブジェクト モデルを公開します。

データセットには、型指定されたデータセットと型指定されていないデータセットがあります。詳細については、後の「型指定されたデータセットと型指定されていないデータセット」を参照してください。型指定されたデータセットは、.xsd ファイルからスキーマ (テーブルと列の構造体) を派生させるので、プログラミングが簡単です。アプリケーションでは、型指定されたデータセットと型指定されていないデータセットのどちらでも使用できます。ただし、型指定されたデータセットを使用した方が、Visual Studio でより多くのツールがサポートされているため、データセットに関するプログラミングが簡単になり、エラーも起こりにくくなります。

型指定されたデータセットは、データ ソース構成ウィザードを実行するか、[プロジェクト] メニューの [新しい項目の追加] で [データセット] 項目を追加して、作成します。詳細については、「方法 : 型指定されたデータセットを作成する」を参照してください。

型指定されていないデータセットは、ツールボックスから [データセット] 項目を Windows フォーム デザイナまたはコンポーネント デザイナにドラッグして、作成します。

データセットを作成したら、データセット デザイナで編集します。

.NET Framework 名前空間の次の部分を使用して、型指定されたデータセットと型指定されていないデータセットを作成して操作します。

データセットは、System.Data 名前空間内にあります。
システム データ データセット名前空間

データセットのオブジェクトは、プロパティやコレクションなどの標準的なプログラミング構造によって公開されます。たとえば、次のように公開されます。

データセットへのデータの読み込み

既定では、データセットには実際のデータは含まれていません。データセットにデータを読み込む操作は、実際にはデータセットを構成する個々の DataTable オブジェクトにデータを読み込む操作を意味します。TableAdapter クエリを実行するか、またはデータ アダプタ (たとえば、SqlDataAdapter) のコマンドを実行して、データ テーブルにデータを読み込みます。データセットにデータを読み込む場合は、各種のイベントが発生したり、制約が検査されたりします。データセットへのデータの読み込みの詳細については、「アプリケーションへのデータのフェッチ」を参照してください。

データセットにデータを読み込むコードは、[データ ソース] ウィンドウから Windows アプリケーションのフォームに項目をドラッグしたときに、フォームのロード イベント ハンドラに自動的に追加されます。詳細については、「チュートリアル : Windows アプリケーションのフォームでのデータの表示」の手順を参照してください。

TableAdapter を使用してデータセットにデータを読み込む例を次に示します。

Me.CustomersTableAdapter.Fill(Me.NorthwindDataSet.Customers)
this.customersTableAdapter.Fill(this.northwindDataSet.Customers);

データセットにデータを読み込むにはさまざまな方法があります。

  • データ ウィザードなどのデザイン時ツールを使用してデータセットを作成した場合、TableAdapter の Fill メソッドを呼び出してください (TableAdapter は、既定の Fill メソッドで作成されます。ただし、名前を変更できるため、実際には別の名前になっている場合もあります)。詳細については、「方法 : データセットにデータを読み込む」の「TableAdapter を使用したデータセットへのデータの読み込み」のセクションを参照してください。

  • DataAdapter の Fill メソッドを呼び出します。詳細については、「DataAdapter からの DataSet の読み込み (ADO.NET)」を参照してください。

  • DataRow オブジェクトを作成してテーブルの DataRowCollection コレクションにそれらを追加することにより、データセットのテーブルに手動でデータを読み込みます。これは実行時にだけ行うことができます。デザイン時には DataRowCollection コレクションを設定できません。詳細については、「DataTable へのデータの追加」を参照してください。

  • XML のドキュメントまたはストリームをデータセットに読み込みます。詳細については、ReadXml メソッドを参照してください。カスタマイズ例については、「チュートリアル : データセットへの XML データの読み込み」を参照してください。

  • 他のデータセットの内容をマージ (コピー) します。この方法は、アプリケーションがいくつかの異なるソース (複数の XML Web サービスなど) からデータセットを取得し、それを 1 つのデータセットに統合する必要がある場合に便利です。詳細については、「DataSet の内容のマージ (ADO.NET)」を参照してください。

  • 他の DataTable の内容をマージ (コピー) します。

データセット内のデータのデータベースへの保存

データセット内のレコードが変更された場合は、変更をデータベースにも反映する必要があります。データセットの変更をデータベースに書き込むには、データセットとその対応するデータベースの間でやり取りを行う TableAdapter または DataAdapter の Update メソッドを呼び出します。

Visual Studio のデータ デザイン ツールを使用する場合、TableAdapter の Update メソッドを呼び出し、保存するデータ テーブルを渡して、データをデータベースに送信します。次に例を示します。

CustomersTableAdapter.Update(NorthwindDataSet.Customers)
customersTableAdapter.Update(northwindDataSet.Customers);

更新処理をより綿密に制御するには、TableAdapter の DBDirect メソッドのいずれかを呼び出すことで、各データ行の個別の値を渡すことができます。詳細については、「方法 : TableAdapter を使用してデータを更新する」および「チュートリアル : TableAdapter DBDirect メソッドを使用してデータを保存する」を参照してください。

個別のレコードを操作するために使用される DataRow クラスには、RowState プロパティが含まれています。このプロパティの値は、データ テーブルがデータベースから最初に読み込まれた後で行が変更されているかどうか、およびどのように変更されているかを示します。使用できる値は、DeletedModifiedAdded、および Unchanged です。TableAdapter と DataAdapter の Update メソッドは、RowState プロパティの値を調べて、どのレコードをデータベースに書き込み、どのデータベース コマンド (InsertCommand、UpdateCommand、DeleteCommand) を起動するかを決定します。

データ更新の詳細については、「データの保存」を参照してください。

データセット内でのレコード間の移動

データセットは完全に非接続のデータ コンテナであるため、ADO レコードセットとは異なり、現在のレコードという概念をサポートしていません。その代わり、データセット内のすべてのレコードをいつでも使用できます。

現在のレコードが存在しないため、現在のレコードを指す特定のプロパティはありません。また、レコード間で移動するためのメソッドやプロパティもありません (後のメモを参照)。データセット内の個別のテーブルにはオブジェクトとしてアクセスできます。各テーブルは、行のコレクションを公開します。このコレクションは他のすべてのコレクションと同じように扱うことができ、コレクションのインデックスによって行にアクセスしたり、プログラミング言語でコレクション固有のステートメントを使用したりできます。

たとえば、Customers テーブルの 4 行目を取得するには、次のようなコードを使用します。

TextBox1.Text = NorthwindDataSet.Customers(3).ContactName
textBox1.Text = northwindDataSet.Customers[3].ContactName;
8bw9ksd6.alert_note(ja-jp,VS.90).gifメモ :

フォーム内のコントロールをデータセットにバインドする場合、BindingNavigator コンポーネントを使用して、各レコードへのアクセスを簡便化できます。詳細については、「方法 : Windows フォームでデータ間を移動する」を参照してください。

LINQ to DataSet

LINQ to DataSet を使用すれば、DataSet オブジェクトのデータを対象に 統合言語クエリ (LINQ: Language-Integrated Query) を実行することが可能になります。詳細については、「LINQ to DataSet」を参照してください。

データセットと XML

データセットは、XML で表すことができるデータのリレーショナル ビューです。データセットと XML の間のそのような関係により、データセットでは次のような機能を利用できます。

  • データセットの構造、つまりテーブル、列、リレーションシップ、および制約を XML スキーマ内で定義できます。構造化された情報を格納しているスキーマに対して、データセットは ReadXmlSchema メソッドと WriteXmlSchema メソッドを使用して読み取りおよび書き込みを行うことができます。スキーマが存在しない場合、データセットは、リレーショナルに組み立てられる XML ドキュメント内のデータから InferXmlSchema メソッドを使用してスキーマを推論できます。XML のスキーマの詳細については、「XML スキーマの作成」を参照してください。

  • データセット クラスを作成して、データ構造体を定義するスキーマ情報を取り込むことができます。これを型指定されたデータセットと呼びます。型指定されたデータセットを作成する方法については、「方法 : 型指定されたデータセットを作成する」を参照してください。

  • データセットの ReadXml メソッドを使用して、XML のドキュメントやストリームをデータセットに読み込むことができます。また、データセットの WriteXml メソッドを使用して、データセットを XML として書き出すこともできます。XML はアプリケーション間でデータを交換するための標準形式であるため、これにより、ほかのアプリケーションから送信された XML 形式の情報をデータセットに読み込むことができます。同様に、データセットのデータを XML のストリームまたはドキュメントとして書き出すことにより、ほかのアプリケーションとデータを共有したり、単に標準形式で保存したりできます。

  • データセットまたはデータ テーブルの内容の XML ビュー (XmlDataDocument オブジェクト) を作成し、リレーショナル メソッド (データセットによる) または XML メソッドのいずれかを使用して、データを表示および操作できます。2 つのビューは、変更されるたびに自動的に同期をとります。

型指定されたデータセットと型指定されていないデータセット

型指定されたデータセットは、まず基本 DataSet クラスから派生し、次にデータセット デザイナの情報を使用して生成されるデータセットです。この情報は .xsd ファイルに格納されており、厳密に型指定された新しいデータセット クラスの生成に使用されます。スキーマの情報 (テーブルや列など) は、新しいデータセット クラスの最上位のオブジェクトとプロパティとして生成され、組み込まれます。型指定されたデータセットは、基本の DataSet クラスから継承するため、型指定されたクラスでは、DataSet クラスのすべての機能を使用できます。また、DataSet クラスのインスタンスをパラメータとして取るメソッドで使用できます。

対照的に、型指定されていないデータセットには対応する組み込みスキーマがありません。型指定されたデータセットと同様に、型指定されていないデータセットにもテーブルや列などが含まれますが、それはコレクションとしてだけ公開されます。ただし、型指定されていないデータセット内にテーブルなどのデータ要素を手動で作成した後で、データセットの WriteXmlSchema メソッドを使用してデータセットの構造をスキーマとしてエクスポートできます。

型指定されたデータセットと型指定されていないデータセットにおけるデータ アクセスの比較

型指定されたデータセットのクラスには、オブジェクト モデルが格納されます。このオブジェクト モデルには、テーブルと列の実際の名前を値として格納するプロパティが格納されます。たとえば、型指定されたデータセットで作業している場合は、次に示すコードを使用して列を参照できます。

' This accesses the CustomerID column in the first row of the Customers table.
Dim customerIDValue As String = NorthwindDataSet.Customers(0).CustomerID
// This accesses the CustomerID column in the first row of the Customers table.
string customerIDValue = northwindDataSet.Customers[0].CustomerID;

一方、型指定されていないデータセットで作業している場合は、次に示すコードを使用します。

Dim customerIDValue As String = _
    CType(dataset1.Tables("Customers").Rows(0).Item("CustomerID"), String)
string customerIDValue = (string)
    dataset1.Tables["Customers"].Rows[0]["CustomerID"];

型付きアクセスの方が読みやすいだけでなく、Visual Studioコード エディタの IntelliSense によって完全にサポートされています。扱いやすさに加えて、型指定されたデータセットの構文ではコンパイル時に型チェックが行われるため、データセット メンバに値を割り当てる場合にエラーの発生する可能性が低くなります。DataSet 内の列の名前を変更して、アプリケーションをコンパイルすると、ビルド エラーが発生します。[タスク一覧] 内のビルド エラーをダブルクリックすると、変更前の列名を参照するコード行に直接移動できます。実行時のテーブルや列へのアクセスも、型指定されたデータセットの方が少し速くなります。これは、アクセスが実行時にコレクションを通して決定される代わりに、コンパイル時に決定されるためです。

型指定されたデータセットには多くの利点がありますが、型指定されていないデータセットを使用すると便利な状況も各種あります。最も明らかな状況は、データセットに対して使用できるスキーマがない場合です。この状況は、たとえば、アプリケーションがデータセットを返すコンポーネントとやり取りするときに、その構造が事前にわかっていない場合に生じます。同様に、操作対象のデータが予測可能な静的構造を持っていない場合もあります。そのような場合、型指定されたデータセットを使用するのは実用的ではありません。なぜなら、データ構造が変更されるたびに型指定されたデータセット クラスを再生成する必要があるためです。

より一般的には、使用可能なスキーマなしでデータセットを動的に作成する場合が多くあります。そのような場合、リレーショナル方法でデータを表すことができる限り、データセットは単に情報を保持することができる便利な構造です。同時に、ほかのプロセスに渡すために情報をシリアル化したり XML ファイルに書き出したりするデータセットの機能も利用できます。

データセットにおける大文字と小文字の区別

データセット内のテーブル名や列名は、既定で大文字と小文字が区別されません。つまり、データセット内の "Customers" というテーブルは、"customers" という形でも参照できます。これは、SQL Server の既定の動作などの多くのデータベースにおける名前付け規則に対応しています。これらのデータベースでは、データ要素の名前を大文字と小文字の違いだけでは区別できません。

8bw9ksd6.alert_note(ja-jp,VS.90).gifメモ :

データセットとは異なり、XML ドキュメントでは大文字と小文字が区別されるため、スキーマで定義するデータ要素の名前では大文字と小文字が区別されます。たとえば、スキーマ プロトコルでは、同じスキーマで "Customers" という名前のテーブルと "customers" という名前の別のテーブルを定義できます。そのため、大文字と小文字の違いしかない要素を含むスキーマを使用してデータセット クラスを生成すると、名前が競合することがあります。

ただし、データセット内でデータを解釈するときに、大文字と小文字の区別が考慮される場合もあります。たとえば、データセット テーブル内のデータにフィルタをかける場合には、検索条件との比較で大文字と小文字を区別するかどうかによって異なる結果が返されることがあります。フィルタ処理、検索、および並べ替えにおける大文字と小文字の区別は、データセットの CaseSensitive プロパティを設定することによって制御できます。データセット内のすべてのテーブルは、このプロパティの値を既定で継承します。各テーブルについてこのプロパティをオーバーライドするには、そのテーブルの CaseSensitive プロパティを設定します。

関連するテーブルと DataRelation オブジェクト

データセットに複数のテーブルが含まれる場合は、テーブル間に情報のリレーションシップが存在する可能性があります。データセットには本質的にそのようなリレーションシップについての情報は含まれていません。したがって、関連し合うテーブル内のデータを操作する場合には、データセット内のテーブル間のリレーションシップを記述する DataRelation オブジェクトを作成します。詳細については、「方法 : 関連する DataTable のレコードにアクセスする」を参照してください。DataRelation オブジェクトを使用することにより、親レコードに関連する子レコードおよび子レコードに関連する親レコードをプログラムでフェッチできます。詳細については、「データセットのリレーションシップ」を参照してください。データベースに複数のテーブル間のリレーションシップが格納されている場合、デザイン ツールによって DataRelation オブジェクトが自動作成されます。

たとえば、Northwind というデータベースに顧客データと注文データが含まれるとします。Customers テーブルには、次のようなレコードが含まれています。

CustomerID   CompanyName               City
ALFKI        Alfreds Futterkiste       Berlin
ANTON        Antonio Moreno Taquerias  Mexico D.F.
AROUT        Around the Horn           London

データセットには、注文情報を含む別のテーブルも含まれています。この Orders テーブルには、顧客 ID が外部キー列として含まれています。Orders テーブルの一部の列だけを選択すると、次のようになります。

OrderId    CustomerID    OrderDate
10692      ALFKI         10/03/1997
10702      ALFKI         10/13/1997
10365      ANTON         11/27/1996
10507      ANTON         4/15/1997

各顧客が複数の注文を行う場合があるため、顧客と注文の間には一対多リレーションシップがあります。たとえば、上のテーブルでは、ALFKI という顧客からの注文が 2 つあります。

DataRelation オブジェクトを使用して、子テーブルまたは親テーブルから関連するレコードを取得できます。たとえば、ANTON という顧客を記述したレコードを操作しているときに、この顧客の注文を記述したレコードのコレクションを取得できます。詳細については、「GetChildRows」を参照してください。同様に、OrderId 10507 を表すレコードを操作しているときに、リレーションシップ オブジェクトをたどって、親 ANTON に対するレコードを取得できます。詳細については、「GetParentRow」を参照してください。

制約

ほとんどのデータベースと同様に、データセットはデータの整合性を保証する手段として制約をサポートしています。制約は、テーブルの行を挿入、更新、または削除するときに適用される規則です。2 つの種類の制約を定義できます。

  • 列の新しい値がテーブル内で重複しないことをチェックする UNIQUE 制約。

  • マスター テーブル内のレコードが更新または削除されるときに関連する子レコードをどのように更新するかの規則を定義する外部キーの制約。たとえば、子レコードが作成される前に、外部キーの制約により親レコードの存在を確認します。

データセットでは、制約に個別のテーブル (外部キーの制約の場合) または列 (列の値が重複しないことを保証する UNIQUE 制約の場合) が関連付けられます。制約は、UniqueConstraint 型または ForeignKeyConstraint 型のオブジェクトとして実装されます。これらの制約は、DataTableConstraints コレクションに追加されます。また、DataColumnUnique プロパティを true に設定するだけでも、UNIQUE 制約を指定できます。

データセット自体は、制約が適用されるかどうかを指定するブール型の EnforceConstraints プロパティをサポートしています。既定では、このプロパティは true に設定されます。ただし、制約を一時的にオフにすると便利な場合もあります。最も一般的な例は、レコードの変更によって一時的に無効な状態が発生するような場合です。そのような場合は、変更を完了して (それによって有効な状態に戻って) から、制約を再び有効にできます。

Visual Studio では、データセットを定義するときに制約が暗黙に作成されます。データセットに主キーを追加すると、その主キー列に対して UNIQUE 制約が暗黙に作成されます。それ以外の列に UNIQUE 制約を指定するには、その列の Unique プロパティを true に設定します。

外部キーの制約を作成するには、データセット内に DataRelation オブジェクトを作成します。DataRelation オブジェクトを使用すると、関連するレコードに関する情報をプログラムで取得できるだけでなく、外部キーの制約の規則を定義できます。

データセットの拡張プロパティ

拡張プロパティは、.xsd ファイルからデータセットを生成する際に名前の競合が発生した場合に、名前のマッピングを提供します。.xsd ファイル内の識別子が、データセットの生成元によって作成された名前と異なる場合、msprop 名前空間でそのデータセットに拡張プロパティが追加されます。生成される可能性のある拡張プロパティを以下の表に示します。

オブジェクト

拡張プロパティ

DataSet

msprop:Generator_UserDSName

msprop:Generator_DataSetName

DataTable

msprop:Generator_UserTableName

msprop:Generator_TablePropName

msprop:Generator_TableVarName

msprop:Generator_TableClassName

msprop:Generator_RowClassName

msprop:Generator_RowEvHandlerName

msprop:Generator_RowEvArgName

DataColumn

msprop:Generator_UserColumnName

msprop:Generator_ColumnPropNameInTable

msprop:Generator_ColumnVarNameInTable

msprop:Generator_ColumnPropNameInRow

参照

その他の技術情報

アプリケーションでデータを受け取る準備

データ アクセスを使用した作業の開始

Visual Studio でのデータへの接続

アプリケーションへのデータのフェッチ

Windows アプリケーションのフォームでのデータの表示

アプリケーションでのデータ編集

データの検証

データの保存