型指定された DataSet 内の TableAdapters は、データベースへの接続、コマンドの発行、結果の DataTable の設定を自動的に処理します。 ただし、これらの詳細を自分で管理したい場合もあります。このチュートリアルでは、TableAdapter のデータベース接続とコマンド レベルの設定にアクセスする方法について説明します。
イントロダクション
チュートリアル シリーズ全体を通して、型指定された DataSet を使用して、階層化アーキテクチャのデータ アクセス層とビジネス オブジェクトを実装しました。 最初のチュートリアルで説明したように、Typed DataSet s DataTable はデータのリポジトリとして機能しますが、TableAdapters はデータベースと通信して基になるデータを取得および変更するためのラッパーとして機能します。 TableAdapters は、データベースの操作に伴う複雑さをカプセル化し、データベースに接続したり、コマンドを発行したり、結果を DataTable に設定したりするコードを記述する必要をなくします。
ただし、TableAdapter の深さを掘り下げ、ADO.NET オブジェクトで直接動作するコードを記述する必要がある場合があります。 たとえば、トランザクション内のデータベース変更のラッピングに関するチュートリアルでは、トランザクションを開始、コミット、ロールバックするためのメソッドをADO.NETのTableAdapterに追加しました。 これらのメソッドは、TableAdapter SqlTransaction
オブジェクトに割り当てられた、手動で作成された内部のSqlCommand
オブジェクトを使用しました。
このチュートリアルでは、TableAdapter のデータベース接続とコマンド レベルの設定にアクセスする方法について説明します。 具体的には、基になる接続文字列とコマンド のタイムアウト設定にアクセスできる機能を ProductsTableAdapter
に追加します。
ADO.NET を使用したデータの操作
Microsoft .NET Framework には、データを操作するために特別に設計された多数のクラスが含まれています。
System.Data
名前空間内にあるこれらのクラスは、ADO.NET クラスと呼ばれます。 ADO.NET 傘の下にあるクラスの一部は、特定の データ プロバイダーに関連付けられています。 データ プロバイダーは、ADO.NET クラスと基になるデータ ストアの間で情報を流すことができる通信チャネルと考えることができます。 OleDb や ODBC などの一般化されたプロバイダーと、特定のデータベース システム用に特別に設計されたプロバイダーがあります。 たとえば、OleDb プロバイダーを使用して Microsoft SQL Server データベースに接続することは可能ですが、SqlClient プロバイダーは、SQL Server 専用に設計および最適化されているため、はるかに効率的です。
プログラムによってデータにアクセスする場合、次のパターンが一般的に使用されます。
- データベースへの接続を確立します。
- コマンドを発行します。
-
SELECT
クエリの場合は、結果のレコードを操作します。
これらの各手順を実行するための個別の ADO.NET クラスがあります。 たとえば、SqlClient プロバイダーを使用してデータベースに接続するには、 SqlConnection
クラスを使用します。 データベースに INSERT
、 UPDATE
、 DELETE
、または SELECT
コマンドを発行するには、 SqlCommand
クラスを使用します。
トランザクション チュートリアル内のデータベース変更の折り返しを除き、TableAdapters 自動生成コードには、データベースへの接続、コマンドの発行、データの取得、DataTable へのデータの設定に必要な機能が含まれているため、低レベルの ADO.NET コードを記述する必要はありません。 ただし、これらの低レベルの設定をカスタマイズする必要がある場合があります。 次のいくつかの手順では、TableAdapters によって内部的に使用される ADO.NET オブジェクトをタップする方法について説明します。
手順 1: Connection プロパティを使用して調べる
各 TableAdapter クラスには、データベース接続情報を指定する Connection
プロパティがあります。 このプロパティのデータ型と ConnectionString
値は、TableAdapter 構成ウィザードで選択した内容によって決まります。 最初に Typed DataSet に TableAdapter を追加すると、このウィザードによってデータベース ソースが要求されることを思い出してください (図 1 を参照)。 この最初の手順のドロップダウン リストには、構成ファイルで指定されたデータベースと、サーバー エクスプローラーのデータ接続内の他のデータベースが含まれます。 使用するデータベースがドロップダウン リストに存在しない場合は、[新しい接続] ボタンをクリックして必要な接続情報を指定することで、新しいデータベース接続を指定できます。
図 1: TableAdapter 構成ウィザードの最初の手順 (フルサイズの画像を表示する] をクリックします)
TableAdapter の Connection
プロパティのコードを調べてみましょう。
データ アクセス層の作成に関するチュートリアルで説明したように、自動生成された TableAdapter コードを表示するには、[クラス ビュー] ウィンドウに移動し、適切なクラスにドリルダウンして、メンバー名をダブルクリックします。
[表示] メニューに移動し、[クラス ビュー] を選択して (または Ctrl + Shift + C キーを押して) クラス ビュー ウィンドウに移動します。 [クラス ビュー] ウィンドウの上半分から、 NorthwindTableAdapters
名前空間にドリルダウンし、 ProductsTableAdapter
クラスを選択します。 これにより、図 2 に示すように、クラス ビューの下半分に ProductsTableAdapter
のメンバーが表示されます。
Connection
プロパティをダブルクリックすると、そのコードが表示されます。
図 2: クラス ビューの Connection プロパティを Double-Click して自動生成されたコードを表示する
TableAdapter の Connection
プロパティとその他の接続関連のコードは次のとおりです。
private System.Data.SqlClient.SqlConnection _connection;
private void InitConnection() {
this._connection = new System.Data.SqlClient.SqlConnection();
this._connection.ConnectionString =
ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}
internal System.Data.SqlClient.SqlConnection Connection {
get {
if ((this._connection == null)) {
this.InitConnection();
}
return this._connection;
}
set {
this._connection = value;
if ((this.Adapter.InsertCommand != null)) {
this.Adapter.InsertCommand.Connection = value;
}
if ((this.Adapter.DeleteCommand != null)) {
this.Adapter.DeleteCommand.Connection = value;
}
if ((this.Adapter.UpdateCommand != null)) {
this.Adapter.UpdateCommand.Connection = value;
}
for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
if ((this.CommandCollection[i] != null)) {
((System.Data.SqlClient.SqlCommand)
(this.CommandCollection[i])).Connection = value;
}
}
}
}
TableAdapter クラスがインスタンス化されると、 _connection
メンバー変数は null
と等しくなります。
Connection
プロパティにアクセスすると、まず、_connection
メンバー変数がインスタンス化されているかどうかを確認します。 存在しない場合は、 InitConnection
メソッドが呼び出されます。 _connection
をインスタンス化し、その ConnectionString
プロパティを TableAdapter 構成ウィザードの最初の手順で指定した接続文字列値に設定します。
Connection
プロパティは、SqlConnection
オブジェクトに割り当てることもできます。 これにより、新しい SqlConnection
オブジェクトが各 TableAdapter SqlCommand
オブジェクトに関連付けられます。
手順 2: Connection-Level 設定を公開する
接続情報は TableAdapter 内にカプセル化されたままで、アプリケーション アーキテクチャ内の他のレイヤーからはアクセスできません。 ただし、TableAdapter の接続レベルの情報にアクセスしたり、クエリ、ユーザー、または ASP.NET ページでカスタマイズしたりする必要がある場合があります。
ProductsTableAdapter
DataSet のNorthwind
を拡張して、TableAdapter で使用される接続文字列の読み取りまたは変更にビジネス ロジック レイヤーで使用できるConnectionString
プロパティを含めます。
注
接続文字列は、使用するプロバイダー、データベースの場所、認証資格情報、その他のデータベース関連の設定など、データベース接続情報を指定する文字列です。 さまざまなデータ ストアとプロバイダーで使用される接続文字列パターンの一覧については、 ConnectionStrings.com を参照してください。
データ アクセス層の作成チュートリアルで説明したように、型指定された DataSet の自動生成クラスは、部分クラスを使用して拡張できます。 まず、ConnectionAndCommandSettings
フォルダーの下に ~/App_Code/DAL
という名前の新しいサブフォルダーを作成します。
図 3: 名前付きのサブフォルダーを追加する ConnectionAndCommandSettings
ProductsTableAdapter.ConnectionAndCommandSettings.cs
という名前の新しいクラス ファイルを追加し、次のコードを入力します。
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace NorthwindTableAdapters
{
public partial class ProductsTableAdapter
{
public string ConnectionString
{
get
{
return this.Connection.ConnectionString;
}
set
{
this.Connection.ConnectionString = value;
}
}
}
}
この部分クラスは、public
という名前のConnectionString
プロパティを ProductsTableAdapter
クラスに追加します。これにより、任意のレイヤーが TableAdapter の基になる接続の接続文字列を読み取ったり更新したりできるようになります。
この部分クラスを作成 (および保存) したら、 ProductsBLL
クラスを開きます。 既存のメソッドのいずれかに移動し、 Adapter
で入力し、ピリオド キーを押して IntelliSense を起動します。 IntelliSense で使用できる新しい ConnectionString
プロパティが表示されます。つまり、プログラムで BLL からこの値を読み取ったり調整したりすることができます。
接続オブジェクト全体の公開
この部分クラスは、基になる接続オブジェクトの 1 つのプロパティ ( ConnectionString
) のみを公開します。 TableAdapter の制限を超えて接続オブジェクト全体を使用できるようにする場合は、 Connection
プロパティの保護レベルを変更することもできます。 手順 1 で調べた自動生成されたコードでは、TableAdapter の Connection
プロパティが internal
としてマークされていることが示されています。つまり、同じアセンブリ内のクラスのみがアクセスできます。 ただし、これは TableAdapter の ConnectionModifier
プロパティを使用して変更できます。
Northwind
DataSet を開き、デザイナーでProductsTableAdapter
をクリックし、[プロパティ] ウィンドウに移動します。
ConnectionModifier
が既定値 (Assembly
) に設定されていることがわかります。 型指定されたデータセットのアセンブリの外部で Connection
プロパティを使用できるようにするには、 ConnectionModifier
プロパティを Public
に変更します。
図 4: Connection
プロパティのアクセシビリティ レベルは、 ConnectionModifier
プロパティを使用して構成できます (フルサイズの画像を表示する をクリックします)。
DataSet を保存し、 ProductsBLL
クラスに戻ります。 前と同様に、既存のメソッドのいずれかに移動し、 Adapter
を入力し、ピリオド キーを押して IntelliSense を起動します。 この一覧には Connection
プロパティが含まれている必要があります。つまり、BLL から接続レベルの設定をプログラムで読み取ったり割り当てたりできるようになりました。
手順 3: Command-Related プロパティを調べる
TableAdapter は、既定で自動生成された INSERT
、 UPDATE
、および DELETE
ステートメントを持つメイン クエリで構成されます。 このメイン クエリの INSERT
、 UPDATE
、および DELETE
ステートメントは、TableAdapter のコードで、 Adapter
プロパティを介して ADO.NET データ アダプター オブジェクトとして実装されます。
Connection
プロパティと同様に、Adapter
プロパティのデータ型は、使用されるデータ プロバイダーによって決まります。 これらのチュートリアルでは SqlClient プロバイダーを使用するため、 Adapter
プロパティの型は SqlDataAdapter
です。
TableAdapter の Adapter
プロパティには、SqlCommand
、INSERT
、およびUPDATE
ステートメントを発行するために使用する、DELETE
型の 3 つのプロパティがあります。
InsertCommand
UpdateCommand
DeleteCommand
SqlCommand
オブジェクトは、特定のクエリをデータベースに送信する役割を担い、実行するアドホック SQL ステートメントまたはストアド プロシージャを含む CommandText
、Parameters
オブジェクトのコレクションであるSqlParameter
などのプロパティを持ちます。
「データ アクセス層の作成」チュートリアルで説明したように、これらのコマンド オブジェクトは [プロパティ] ウィンドウでカスタマイズできます。
TableAdapter には、メイン クエリに加えて、呼び出されたときに指定したコマンドをデータベースにディスパッチする可変の数のメソッドを含めることができます。 メイン クエリのコマンド オブジェクトと追加のすべてのメソッドのコマンド オブジェクトは、TableAdapter の CommandCollection
プロパティに格納されます。
次の 2 つのプロパティとそのサポート メンバー変数とヘルパー メソッドについて、ProductsTableAdapter
DataSet のNorthwind
によって生成されたコードを少し見てみましょう。
private System.Data.SqlClient.SqlDataAdapter _adapter;
private void InitAdapter() {
this._adapter = new System.Data.SqlClient.SqlDataAdapter();
... Code that creates the InsertCommand, UpdateCommand, ...
... and DeleteCommand instances - omitted for brevity ...
}
private System.Data.SqlClient.SqlDataAdapter Adapter {
get {
if ((this._adapter == null)) {
this.InitAdapter();
}
return this._adapter;
}
}
private System.Data.SqlClient.SqlCommand[] _commandCollection;
private void InitCommandCollection() {
this._commandCollection = new System.Data.SqlClient.SqlCommand[9];
... Code that creates the command objects for the main query and the ...
... ProductsTableAdapter�s other eight methods - omitted for brevity ...
}
protected System.Data.SqlClient.SqlCommand[] CommandCollection {
get {
if ((this._commandCollection == null)) {
this.InitCommandCollection();
}
return this._commandCollection;
}
}
Adapter
プロパティとCommandCollection
プロパティのコードは、Connection
プロパティのコードとよく似たコードです。 プロパティで使用されるオブジェクトを保持するメンバー変数があります。 アクセサー get
プロパティは、まず、対応するメンバー変数が null
されているかどうかを確認します。 その場合は、メンバー変数のインスタンスを作成し、コマンド関連のコア プロパティを割り当てる初期化メソッドが呼び出されます。
手順 4: Command-Level 設定を公開する
理想的には、コマンド レベルの情報はデータ アクセス層内にカプセル化されたままにする必要があります。 ただし、この情報がアーキテクチャの他のレイヤーで必要な場合は、接続レベルの設定と同様に、部分クラスを介して公開できます。
TableAdapter には 1 つの Connection
プロパティしかないため、接続レベルの設定を公開するためのコードはかなり簡単です。 TableAdapter は複数のコマンド オブジェクト ( InsertCommand
、 UpdateCommand
、 DeleteCommand
、および CommandCollection
プロパティ内の可変数のコマンド オブジェクト) を持つ可能性があるため、コマンド レベルの設定を変更する場合は、もう少し複雑になります。 コマンド レベルの設定を更新するときは、これらの設定をすべてのコマンド オブジェクトに反映する必要があります。
たとえば、TableAdapter に実行に非常に長い時間がかかった特定のクエリがあるとします。 TableAdapter を使用してこれらのクエリのいずれかを実行する場合は、コマンド オブジェクトの CommandTimeout
プロパティを増やすことができます。 このプロパティは、コマンドの実行を待機する秒数を指定し、既定値は 30 です。
BLL によって CommandTimeout
プロパティを調整できるようにするには、手順 2 で作成した部分クラス ファイル (public
) を使用して、次のProductsDataTable
メソッドをProductsTableAdapter.ConnectionAndCommandSettings.cs
に追加します。
public void SetCommandTimeout(int timeout)
{
if (this.Adapter.InsertCommand != null)
this.Adapter.InsertCommand.CommandTimeout = timeout;
if (this.Adapter.DeleteCommand != null)
this.Adapter.DeleteCommand.CommandTimeout = timeout;
if (this.Adapter.UpdateCommand != null)
this.Adapter.UpdateCommand.CommandTimeout = timeout;
for (int i = 0; i < this.CommandCollection.Length; i++)
if (this.CommandCollection[i] != null)
this.CommandCollection[i].CommandTimeout = timeout;
}
このメソッドは、BLL またはプレゼンテーション レイヤーから呼び出して、その TableAdapter インスタンスによって発生するすべてのコマンドのタイムアウトを設定できます。
注
Adapter
プロパティとCommandCollection
プロパティはprivate
としてマークされます。つまり、TableAdapter 内のコードからのみアクセスできます。
Connection
プロパティとは異なり、これらのアクセス修飾子は構成できません。 したがって、アーキテクチャ内の他のレイヤーにコマンド レベルのプロパティを公開する必要がある場合は、上記の部分クラス アプローチを使用して、public
コマンド オブジェクトの読み取りまたは書き込みを行うprivate
メソッドまたはプロパティを提供する必要があります。
概要
型指定された DataSet 内の TableAdapters は、データ アクセスの詳細と複雑さをカプセル化するために機能します。 TableAdapters を使用すると、データベースに接続したり、コマンドを発行したり、結果を DataTable に入力したりするために、ADO.NET コードを記述する必要はありません。 それはすべて自動的に処理されます。
ただし、接続文字列の変更や既定の接続またはコマンドのタイムアウト値など、低レベルの ADO.NET の詳細をカスタマイズする必要がある場合があります。 TableAdapter には自動生成された Connection
、 Adapter
、および CommandCollection
のプロパティがありますが、これらは既定で internal
または private
です。 この内部情報を公開するには、部分クラスを使用して TableAdapter を拡張し、 public
メソッドまたはプロパティを含めることができます。 または、TableAdapter Connection
プロパティ アクセス修飾子は、TableAdapter の ConnectionModifier
プロパティを使用して構成できます。
プログラミングに満足!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリードレビュー担当者は、バーナデット・リー、S・レン・ジェイコブ・ラウリセン、テレサ・マーフィー、ヒルトン・ガイズナウでした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにメッセージを送ってください。