更新日: 2009 年 11 月 30 日

C# の内容はこちらに掲載しています。 10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#)

このコンテンツのポイント

  • データセット (DataSet) の使用方法
  • テーブルアダプター (TableAdapter) によるデータの読み込み
  • テーブルアダプターマネージャー (TableAdapterManager) によるデータの更新

今回紹介するコード

Visual Basic
Public Class Form1

    Private Sub CustomersBindingNavigatorSaveItem_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
    Handles CustomersBindingNavigatorSaveItem.Click
        Me.Validate()
        Me.CustomersBindingSource.EndEdit()
        Me.OrdersBindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.NORTHWNDDataSet)

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) Handles MyBase.Load

        Me.CustomersTableAdapter.Fill(Me.NORTHWNDDataSet.Customers)
        Me.OrdersTableAdapter.Fill(Me.NORTHWNDDataSet.Orders)

    End Sub

    Private Sub OrdersBindingSource_AddingNew( _
        ByVal sender As System.Object, _
        ByVal e As System.ComponentModel.AddingNewEventArgs) _
    Handles OrdersBindingSource.AddingNew
        Me.CustomersBindingSource.EndEdit()
    End Sub
End Class
 

目次

  1. はじめに
  2. Windows アプリケーションの開発準備
  3. データ ソースの準備
  4. データベースの修正
  5. データセットの確認とリレーションシップの編集
  6. フォームのデザイン
  7. データ読み込み時の処理
  8. データ保存時の処理
  9. 新規データ入力時の処理

1. はじめに

データベースに常時接続しない「非接続型のデータ アクセス」は、.NET アプリケーションでは主流のデータ アクセス方法です。ここではデータセット (DataSet) を用いた非接続型のデータ アクセス方法について、サンプル アプリケーションを作成しながら解説していきます。

具体的には、以下のような画面を持つ Windows フォーム アプリケーションを作成します。これはマスター/詳細の関係にある顧客テーブルと注文テーブルのデータを表示、編集するためのアプリケーションです。画面上部には顧客データが表示され、その顧客に関連した注文データが画面下部にグリッド表示されます。データの新規作成や保存は、ウィンドウ最上部にあるツール バーにより行えます。

図 1 ここで作成するサンプル アプリケーションの実行画面

ページのトップへ


2. Windows アプリケーションの開発準備

まず、Windows アプリケーションの準備として、プロジェクトを新規作成します。

Visual Studio を起動して、[ファイル] メニューの [新規作成] から [プロジェクト] をクリックし、[新しいプロジェクト] ダイアログを開きます。そして [プロジェクトの種類] で [Windows] を、[テンプレート] では [Window フォーム アプリケーション] を選択します。[プロジェクト名] は任意の名前を指定できます。ここでは「DSWindowsFormsApplication」としています。

図 2 [新しいプロジェクト] ダイアログで Windows フォーム アプリケーションのプロジェクトを新規作成

ページのトップへ


3. データ ソースの準備

次に、データ ソースの設定を行います。データ ソースは、アプリケーションがデータベースからデータを取得する際の取得元となります。この設定は Visual Studio のデータ ソース構成ウィザードを使用して行います。また、データベースとしては、このページ (英語) からダウンロードできる Northwind データベース (NORTHWND.MDF ファイル) を使用します。

まず、Visual Studio の [データ] メニューから [新しいデータ ソースの追加] を選択し、データ ソース構成ウィザードを起動します。最初の画面では、アプリケーションのデータの取得元として [データベース] を選択し、[次へ] ボタンをクリックします。

図 3 [データベース] を選択して、[次へ] ボタンをクリック

続くデータ接続の選択画面では、画面右上にある [新しい接続] ボタンをクリックします。

図 4 右上にある [新しい接続] ボタンをクリック

[新しい接続] ボタンをクリックすると、[接続の追加] ダイアログが開きますので、データ ソースとして [Microsoft SQL Server データベース ファイル]、[データベース ファイル名] としては Northwind データベース (NORTHWND.MDF ファイル) へのパスを指定します。そして [OK] ボタンをクリックしてください。

図 5 [Microsoft SQL Server データベース ファイル] を選択し、NORTHWND.MDF ファイルのパスを指定

データベース サーバーにアクセスしてデータを取得するようなケースでは、この [接続の追加] ダイアログで、データベース サーバーやそのデータベースを選択します。

データ ソース構成ウィザードに戻り、[次へ] ボタンをクリックすると、以下のような確認画面が表示されます。今回は実験としてデータベースの内容を更新しますので、ここでは [はい] をクリックして、データ ファイル (ここでは NORTHWND.MDF ファイルのこと) をプロジェクトにコピーするようにします。

図 6 [はい] をクリックしてデータ ファイルをコピー

次に接続文字列をアプリケーション構成ファイル (.exe.config ファイル) に保存するかどうか聞かれます。ここではそのまま [次へ] ボタンをクリックします。

図 7 設定を変更せず [次へ] ボタンをクリック

最後に、データセット内に指定するデータベース オブジェクトを選択します。今回のサンプルでは Customers テーブルと Orders テーブルを扱いますので、この 2 つのテーブルを選択し、データセット名としては「NORTHWNDDataSet」を指定して、[完了] ボタンをクリックします。これら 2 つのテーブルは、Customers テーブルが顧客データを、Orders テーブルは各顧客の注文データを含んでいます。

図 8 Customers テーブルと Orders テーブルを選択して [完了] ボタンをクリック

以上でデータ ソースの設定は完了です。

Visual Studio の [データ] メニューから [データ ソースの表示] を選ぶと、Visual Studio の左側に、いま作成したデータ ソースがツリー表示されます。この表示は、Customers データ テーブルと Orders データ テーブルの 2 つを含むデータセットである「NORTHWNDDataSet」を示しています。通常、データセットは複数のデータ テーブルを含んでおり、データベースから取得したレコードのデータは、実際にはデータ テーブルに行オブジェクトとして格納されます。

図 9 [データ ソース] ウィンドウの表示

ページのトップへ


4. データベースの修正

以降では、Customers テーブルや Orders テーブルのレコードが編集可能なアプリケーションを作成していくわけですが、Northwind データベースには Orders テーブルのほかに OrdersDetail テーブルという子テーブルがあり、Orders テーブルのレコードを削除する場合などでは、OrdersDetail テーブルのレコードの存在も考慮する必要があります (これら 2 つのテーブル間に制約が設定されているためです)。ここではサンプル アプリケーションでの処理をシンプルにするために、OrdersDetail テーブルをデータベースから削除しておきます。

これには、ソリューション エクスプローラーで [NORTHWND.MDF] の項目をダブルクリックしてサーバー エクスプローラーを開き、[Order Details] の項目を右クリックして、コンテキスト メニューにある [削除] を実行します。

図 10 Order Details テーブルの削除

ページのトップへ


5. データセットの確認とリレーションシップの編集

次に、データセット デザイナーにより、データセット内でのリレーションの編集を行います。

ソリューション エクスプローラーからデータセットの定義である「NORTHWNDDataSet.xsd」の項目をダブルクリックすると、データセット デザイナーにより、いま作成したデータセットが開きます。

図 11 データセット デザイナーにより開いたデータセット

この画面にあるように、データベースでの設定が反映されて、2 つのデータ テーブルにはリレーションシップが設定されているのが分かります。ここではこのリレーションシップを右クリックして、コンテキスト メニューより [リレーションシップの編集] を実行します。これにより次のような画面が開きます。

図 12 リレーションシップの編集を行うための [リレーションシップ] ダイアログ

この画面では [作成する制約の選択] 部分で、先頭の [リレーションシップと外部キー制約の両方] を選択し、[UpdateRule の設定] と [DeleteRule の設定] を [Cascade] に設定してください。この設定により、例えば親側である Customers データ テーブルでデータを削除すると、そのデータに関連する、子側の Orders データ テーブルのデータも自動的に削除されるようになります。

図 13 [リレーションシップと外部キー制約の両方] を選択し、[UpdateRule の設定] と [DeleteRule の設定] を [Cascade] に設定

ページのトップへ


6. フォームのデザイン

それでは次に、フォームのデザインを行います。ソリューション エクスプローラーで Form1.vb をダブルクリックしてフォーム デザイナーで開き、さらに先ほどと同様にしてデータ ソースも表示します。

最初に顧客データを編集するための編集フォームを作成します。これは [データ ソース] ウィンドウの機能により、マウスだけで簡単に完成させることができます。

まず、[データセット] ウィンドウ内にある [Customers] の項目を選択し、現れる [▼] ボタンをクリックしてメニューを開き、[詳細] を選択します (既定では [DataGridView] が選択されています)。そして、この [Customers] の項目をマウスでフォーム上にドラッグ & ドロップしてください。これだけでツールバー付きの編集フォームが自動的に作成されます。同時に 5 つのコンポーネントがアプリケーションに追加されているのが分かります。これらのコンポーネントはフォーム デザイナーの下部に表示されています。

図 14 [Customers] のドラッグ & ドロップにより作成した編集フォーム

続いては、注文データを編集するためのグリッド (DataGridView コントロール) を、いま作成した編集フォームのすぐ下に配置します。

これには、[データ ソース] ウィンドウで [Customers] の項目を開き、次の画面のように、ツリーの一番下にある [Orders] の項目をフォーム上にドラッグ & ドロップしてください。この際には、[Orders] の項目の [▼] ボタンから、[詳細] ではなく、[DataGridView] を選択しておく必要があります。

図 15 [Orders] のドラッグ & ドロップにより作成したグリッド

[データ ソース] ウィンドウには [Orders] の項目が 2 つ存在していますが、必ず [Customers] 配下にある方を使用してください。そうしないと先に設定したリレーションシップが反映されず、フォーム上で連動して動作しません。

以上でフォームが完成ですが、実は編集や保存機能もこれだけでほぼ完成しています。以下では自動作成されているコードを解説しながら、最低限必要な若干の修正を行っていきます。

ページのトップへ


7. データ読み込み時の処理

Form1.vb のコードを開くと、アプリケーションの実行開始時に呼び出される Load イベント ハンドラーである Form1_Load メソッドが次のように記述されています。ここでは Orders テーブルと Customers テーブルに対応した 2 つのテーブルアダプター (OrdersTableAdapter と CustomersTableAdapter) が使用されているのが分かります。

テーブルアダプターは、実際にデータベースにアクセスし、指定されたデータ テーブルにデータを取得したり (Fill メソッド)、データ テーブル内の変更されたデータをデータベースに反映する (Update メソッド) ためのコンポーネントです。

Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'TODO: このコード行はデータを 'NORTHWNDDataSet.Orders' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
    Me.OrdersTableAdapter.Fill(Me.NORTHWNDDataSet.Orders)
    'TODO: このコード行はデータを 'NORTHWNDDataSet.Customers' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
    Me.CustomersTableAdapter.Fill(Me.NORTHWNDDataSet.Customers)

End Sub
 

この Form1_Load メソッドが実行されると、データセットにデータが取得され、フォーム上にデータが表示されます。これは、フォーム上にあるテキスト ボックスや DataGridView コントロールが、データセットにデータ バインディングされているためです (正確には、自動作成されたコンポーネントである、CustomersBindingSource や OrdersBindingSource を経由して、データセットとフォーム上のコントロールはデータ バインディングされています)。

ここでは上記の 2 行のコードの順番を入れ替え、次のコードのように修正します (コメント文は削除しています)。

Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Me.CustomersTableAdapter.Fill(Me.NORTHWNDDataSet.Customers)
    Me.OrdersTableAdapter.Fill(Me.NORTHWNDDataSet.Orders)

End Sub
 

これは、先に Orders データ テーブルにデータを読み込んでしまうと、その親となる Customers データが Customers データテーブルに存在しないという状況が発生し、先ほど設定した外部キー制約に違反してしまうためです。

ページのトップへ


8. データ保存時の処理

自動作成されているコードとしてはもう 1 つ、CustomersBindingNavigatorSaveItem_Click メソッドがあります。このメソッドはツール バー上の保存ボタンがクリックされたときに呼び出されるメソッドです。

Visual Basic
Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click
    Me.Validate()
    Me.CustomersBindingSource.EndEdit()
    Me.TableAdapterManager.UpdateAll(Me.NORTHWNDDataSet)

End Sub
 

ここではまず、フォームの Validate メソッドを呼び出して検証処理を実行します。続いて、CustomersBindingSource の EndEdit メソッドを呼び出していますが、これは顧客データの編集フォームでの編集を確定させるためのものです。これによりフォームで編集された内容がデータセットにすべて反映されます。

このメソッドでは、DataGridView コントロールでの編集を確定させるコードが自動作成されていませんので、次の 1 行 (太字の行) を 3 行目に挿入しておく必要があります。


Me.Validate()
Me.CustomersBindingSource.EndEdit()
Me.OrdersBindingSource.EndEdit()

メソッドの最後の行では、テーブルアダプターマネージャーの UpdateAll メソッドを呼び出しています。テーブルアダプターマネージャーは Visual Studio 2008 で新しく導入された機能で、今回のような複数のテーブルを扱う場合に重要な役割を果たします。従来では、個々のテーブルアダプターの Update メソッドを、その呼び出し順やデータ更新の種類 (編集、挿入、削除) などを考慮しながら使用する必要がありましたが、テーブルアダプターマネージャーは UpdateAll メソッドを呼び出すだけで、それらの処理を行ってくれます。

ページのトップへ


9. 新規データ入力時の処理

実はデータ テーブル間に設定したリレーションシップの外部キー制約に違反してしまう状況がもう 1 つあり得ます。それは、顧客データを新規入力し、さらに同時に、その注文データを入力しようとした場合に起こります。この状況は、注文データが入力される際に、新規入力された顧客データの編集を先に確定することにより回避できます。この処理は、OrdersBindingSource の AddingNew イベント ハンドラーに記述でき、その内容は次のようになります。

Private Sub OrdersBindingSource_AddingNew(ByVal sender As System.Object, ByVal e As System.ComponentModel.AddingNewEventArgs) Handles OrdersBindingSource.AddingNew
    Me.CustomersBindingSource.EndEdit()
End Sub

このイベント ハンドラーは、フォーム デザイナーの下部にある OrderBindingSource コンポーネントを選択し、[プロパティ] ウィンドウで [AddingNew] の欄をダブルクリックすれば自動的に作成されます。

以上でアプリケーションは完成です。最終的なコードは次のようになります。太字の部分が実際に手で入力したコードです。

Public Class Form1

    Private Sub CustomersBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CustomersBindingNavigatorSaveItem.Click
        Me.Validate()
        Me.CustomersBindingSource.EndEdit()
        Me.OrdersBindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.NORTHWNDDataSet)

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Me.CustomersTableAdapter.Fill(Me.NORTHWNDDataSet.Customers)
        Me.OrdersTableAdapter.Fill(Me.NORTHWNDDataSet.Orders)

    End Sub

    Private Sub OrdersBindingSource_AddingNew(ByVal sender As System.Object, ByVal e As System.ComponentModel.AddingNewEventArgs) Handles OrdersBindingSource.AddingNew
        Me.CustomersBindingSource.EndEdit()
    End Sub
End Class

このアプリケーションの実行画面は冒頭で示したとおりです。


Code Recipe

ページのトップへ