ADO.NET を使用して Web サイトデータにアクセスする方法
はじめに
さまざまな Web API を通じて Web サイトと連携できるのは、新しい可能性が広がる魅力的なことです。ただ、API ごとに使い方を一から学び直す必要があるのは少々大変ですよね。
そこで、もっと良い方法があります。CData は、主要な API を ADO.NET データプロバイダーとして実装しています。Google、 QuickBooks、Salesforce、SharePoint に対応しており、さらに対応サービスは増え続けています。
つまり、ADO.NET でデータベースを操作する方法を知っていれば、新たに学ぶことは何もありません。 ADO.NET をまだ知らない方もご安心ください。簡単に習得でき、汎用的に使えるので、学ぶ価値は十分にあります。
この記事では、Google ADO.NET データプロバイダーの使い方を紹介しますが、基本的な考え方はどの ADO.NET データプロバイダーでも同じです。 また、デスクトップの Windows Forms アプリケーションを作成しますが、同じ原理は ADO.NET を使用できるあらゆるプラットフォーム(WPF や ASP.NET など)に適用できます。 つまり、同じアイデアでデスクトップアプリケーションも Web アプリケーションも作成できるのです。
ADO.NET と Google データプロバイダーを使い始めるのは、Visual Studio のデザイナー機能(フルバージョンでも Express エディションでも利用可能)を使えばさらに簡単です。 デザイナーでできることはすべてコードだけでも実現できますし、多くの場合、コードの方が直接的で効率的です。 ただし、これから始める方にとっては、コードジェネレーターの方がシンプルな場合が多いでしょう。この場合、より強力で型安全なクラス群を使えるという利点もあります。
Google データプロバイダーを使うと、ユーザーの Google カレンダー、連絡先、ドキュメント、メール、スプレッドシートなどにアクセスできます。 これらを利用するには、CData から Google Data Provider の試用版をダウンロードしてください。手順に従ってデータプロバイダーをインストールします。
接続
Visual Studio を起動したら、サーバーエクスプローラーを使って新しい Google データソースをセットアップできます。 実際のアプリケーションでは、ユーザー名とパスワードをプログラムで提供する必要がありますが、まず試してみる最も簡単な方法は、 ご自身の Google ユーザー名とパスワードを使うことです。もしアカウントをお持ちでなければ、無料で新規作成できます。
「接続の追加」コマンドを使用し、データソースとして CData Google Data Source を選択します。これが見つからない場合は、データプロバイダーがインストールされていません。
「接続の追加」ダイアログボックスでは、Google アカウントのパスワードとユーザー名を入力するだけです。 これらの情報は、Google アカウントへの接続に必要な詳細を含む接続文字列の作成に使用されます。 接続を使い始める前に、「接続のテスト」ボタンをクリックすることをお勧めします。 「テスト接続に成功しました」というメッセージが表示されるはずです。表示されない場合は、アカウント情報が正しく入力されていないか、インターネット接続に問題がある可能性があります。
接続テストが成功したら、クエリを実行してデータをさらに詳しく確認することもできます。その方法はオンラインヘルプに詳しく説明されているので、ここではコードの作成に進みましょう。
新しい Windows Forms Application(C#)プロジェクトを作成します。Visual Basic でも同様のアプリケーションを同じ方法で作成できますし、WPF や ASP.NET プロジェクトも非常に似た手順で作成できます。
DataSet デザイナー
次の作業は、DataSet デザイナーを使用して TableAdapter を作成することです。TableAdapter は、大まかに言えば DataAdapter を備えた DataSet です。 ただし、TableAdapter の方がより強力で、型安全であり、追加のメソッドも持っています。 これはデザイナーを使うことで、より簡単になるだけでなく、より良いコードが生成される場面の一つです。
プロジェクトを選択して右クリックし、「追加」→「新しい項目」を選択します。「新しい項目の追加」ダイアログボックスが表示されたら、DataSet を選択します。 名前は任意ですが、動作を明確にするため、この例ではデフォルト名の DataSet1 を使用します。

DataSet が作成されたら、DataSet デザイナーを使用して、データベースの操作に必要なオブジェクトを作成できます。
その前に、ADO.NET の仕組みを簡単におさらいしておきましょう。
メモリ内のデータを表す .NET クラスがいくつかあり、その主なものが DataTable です。
また、メモリ内のテーブルと実際のデータベースを接続する DataAdapter クラスもあります。
DataAdapter は「接続文字列」を使用して接続の詳細を指定します。
ADO.NET 4 の新しい概念が TableAdapter です。これは型安全な DataTable と組み込みの DataAdapter を組み合わせたものです。 また、単純な DataTable よりも扱いやすい便利なメソッドとプロパティを持っており、DataSet デザイナーはこれを作成する最も簡単な方法です。
サーバーエクスプローラーで CData Google Data Provider を見ると、Feeds、Views、Services があることがわかります。 Feeds と Views は基本的にデータテーブルで、Feeds は読み書き可能、Views は読み取り専用です。

Feeds セクションには、Calendar、Contact/Groups、Contacts の 3 つのデータテーブルがあることがわかります。
今回はローカルとオンラインの連絡先の同期機能を提供するアプリケーションを作成するため、Contacts テーブルに接続します。
Contacts テーブル用の DataAdapter を作成するには、Contacts テーブルを DataSet デザイナーにドラッグ&ドロップするだけです。 Google データが使用するすべてのカラムを含むデフォルトの DataTable と、DataTable を埋めるための TableAdapter が作成されます。 DataAdapter の一部として SQL クエリを指定してレコードやカラムのサブセットを抽出することもできますが、デフォルトではすべてを抽出します。
この場合、生成された DataAdapter を使えるようにするために、一つだけ小さな作業が必要です。 接続文字列プロパティは設定されていますが、セキュリティ対策としてパスワードは省略されています。 実際のアプリケーションでは、接続文字列をより洗練された方法で管理する必要があるでしょう。一般的な形式は次のとおりです:
Password=<password>;User=<user name>

ターゲットフレームワーク
ここで、些細だけれど知らないと困惑する問題が発生します。 プログラムをそのままビルドまたは実行しようとすると、次のようなエラーメッセージが表示されます:
型または名前空間 "CData" が名前空間に存在しません(アセンブリ参照が不足していませんか)
いいえ、アセンブリ参照は不足していません。プロジェクトは生成されたコードだけで構成されているのに、 エラーメッセージが出るのは不思議に思うかもしれません。
このエラーメッセージの原因は、プロジェクトがデフォルトで .NET Framework 4 Client Profile をターゲットにしているためです。 これは非常に軽量なアプリケーションを作成するために設計された、機能を絞ったプロジェクトタイプです。 ほとんどの場合、これで十分ですが、ADO.NET アプリケーションには追加のアセンブリが必要なため、エラーメッセージが表示されます。
この問題を解決してエラーメッセージを消すには、プロジェクトのプロパティを開き、「アプリケーション」タブでターゲットフレームワークを .NET Framework 4 に変更するだけです。

この後は、問題なくプログラムをビルドまたは実行でき、ポップアップする警告メッセージが示唆するような手動での変更は不要です。
データの読み込み
ここでも、コードに移行するか、デザイナーを使い続けるかを選択できます。今回はフォームデザイナーでフォームを表示してみましょう。 ツールボックスの上部に、新しいコントロール(DataSet1、ContactTableAdapter、TableAdapterManager)が表示されているはずです。

これらのコントロールが表示されない場合は、プロジェクトをビルドまたは実行して作成してから次に進んでください。
次に、DataSet1 と ContactsTableAdapter のインスタンスをフォームにドラッグ&ドロップするだけです。 これで節約できるのは、デフォルトクラスのインスタンスを作成する手間だけで、この方法にはあまりメリットがないとも言えますが、このように行うことができます。
ここからは少しコードを書く必要がありますが、多くはありません。 フォームに 2 つの生成されたデータコントロールを配置したことで、dataSet1 と contactsTableAdapter1 が作成されたので、コードですぐに使い始めることができます。
ボタンをフォームに配置して、そのイベントハンドラーにコードを記述できるようにします。
完全修飾名を使わなくて済むように、プログラムの先頭に次の行を追加します:
using System.Data.CData.Google;
DataAdapter が「データベース」(つまり Google のユーザー名とパスワード)に接続できるように、接続文字列を設定する必要があります:
contactsTableAdapter1.Connection = new GoogleConnection( "Password=password;User=username");
また、Google Contacts データベースからのレコードを格納するための適切な型の DataTable も必要です。 この作業には基本的な DataTable を使用できますが、デザイナーが型安全な DataTable を生成してくれているのに、なぜそうする必要があるでしょうか。
この型安全な DataTable のインスタンスを作成するには、DataSet を使用します:
DataSet1.ContactsDataTable MyTable= new DataSet1.ContactsDataTable();
これで新しいテーブルにデータを入れることができます:
contactsTableAdapter1.Fill(MyTable);
TableAdapter には GetData メソッドもあり、正しい型の DataTable にデータを入れて返してくれます:
DataSet1.ContactsDataTable MyTable = contactsTableAdapter1.GetData();
この時点で、MyTable にはレコードオブジェクトのセットが含まれており、各レコードオブジェクトにはテーブルのカラムに対応するプロパティがあり、すべて正しい型になっています。 これが型安全な DataTable を使用する利点です。
例えば、最初のレコードの FullName を取得するには、次のように書けます:
string name=MyTable[0].FullName;
型安全なテーブルの利点を活かすには、型安全な Row オブジェクトを使用する必要があることに注意してください。
例えば、一般的な DataRow 型を使用して foreach ループでコレクションを走査するには、次のように書く必要があります:
foreach (DataRow row in MyTable) {
name = (string) row["FullName"];
}
フィールドを取得するにはインデックスを使用し、正しいデータ型(string)にキャストする必要があることに注意してください。
これを型安全な方法で同じことを行う場合と比較してみましょう:
foreach(DataSet1.ContactsRow row in MyTable) {
name = row.FullName;
}
この方法では、FullName プロパティを使用し、すでに string 型なのでキャストは不要です。
この種のコーディングの動作を見れば、これがはるかに良い作業方法であることが理解できるはずです。
更新
ここからは、テーブルの更新というより難しい問題に取り組みます。 Fill または GetData メソッドを使用して DataTable にデータを読み込んだら、通常の方法で rows コレクションを操作できます。 つまり、データベースやこの場合の Google アカウントに保存されているデータに何が起きているかを気にせずに、データを変更したり、行を削除したりできます。 しかし、メモリ内で行った変更で外部データを更新したい場合はどうすればよいでしょうか?
ここで TableAdapter の Update メソッドが活躍します。原則として、Update メソッドは TableAdapter を作成するときに自動的に生成されるはずですが、 ほとんどの場合、複雑すぎて生成できず、メソッドは未定義のままになります。幸い、Update メソッドを手動で作成するのは比較的簡単です。
ポイントは、更新を実行する SQL コマンドを提供することです。そのためには、DataTable 内のデータとデータベース内のデータを照合する WHERE 句を提供する必要があります。 ほとんどの場合、WHERE 句は単にキー値でレコードを照合します。 また、変更したいフィールドに新しいデータを格納する SET 句も必要です。例えば:
UPDATE table SET field1=value1 WHERE (key=value2)
これは table に対して更新を実行し、key=value2 のレコードのみを変更し、field1 を value1 に変更します。
これは簡単ですが、TableAdapter は UPDATE コマンドを rows コレクションのすべてのレコードに適用します。 そのため、UPDATE コマンドは各フィールドを更新する値を示すために、定数ではなく変数を使用する必要があります。 ADO.NET では、行のプロパティ名の前に @ を付けることで変数を表します。 例えば、各 ContactsRow オブジェクトには FullName プロパティがあり、外部レコードを更新するには次のようなものを使用します:
UPDATE Contacts SET FullName=@FullName WHERE (Editlink=@Editlink)
これは Contacts テーブルを更新し、Editlink を Editlink プロパティと照合することで、変更されたメモリ内レコードを変更が必要なテーブルレコードと一致させます。 Editlink はこのテーブルのキーであり、一意です。 メモリ内レコードとテーブルレコードが一致したら、FullName フィールドは行オブジェクトの FullName プロパティの内容で更新されます。
Update メソッドを作成するには、DataSet エディターを開き、ContactsTableAdapter のプロパティを確認します。 Update command をクリックし、New を選択します。次に、上記の SQL コマンドを入力すれば完了です。

これで、次のようなコードを書くことができます:
MyTable[0].FullName = "I Programmer"; contactsTableAdapter1.Update(MyTable);
そして Google 連絡先のデータテーブルが更新されます。もちろん、何らかの理由で更新が失敗する可能性は常にあるので、Try-Catch を使用してください。
メモリ内レコードの他のフィールドを変更しても、更新されるのは FullName フィールドのみであることに注意してください。 他のフィールドを変更するには、SQL コマンドにそれらを追加するだけです。
次のステップ
この記事で説明したアイデアを、Google プロバイダーの他のテーブルや、他のプロバイダーにも拡張できるはずです。 これは Web API を操作するためのスマートなアプローチです。DataSet デザイナーも作業を簡単かつ確実にしてくれます。 その型安全な DataSet は LINQ や Entity Framework でも使用できますが、ほとんどの場合、データの取得、変更、更新だけで十分であり、ADO.NET 単体でこれを非常にうまく処理できます。 より複雑なアプローチを検討する価値があるのは、結合やテーブル間のリレーションシップを処理する必要がある場合だけです。