次の方法で共有


データ アクセス層の接続レベルとコマンド レベルの設定を構成する (C#)

作成者: Scott Mitchell

PDF のダウンロード

型指定された DataSet 内の TableAdapters により、データベースへの接続、コマンドの発行、DataTable への結果の追加が自動的に行われます。 ただし、これらの詳細を自分で処理する必要がある場合があります。このチュートリアルでは、TableAdapter のデータベース接続レベルとコマンド レベルの設定にアクセスする方法を学習します。

はじめに

チュートリアル シリーズ全体を通して、型指定された DataSet を使用して、階層化アーキテクチャのデータ アクセス層とビジネス オブジェクトを実装しました。 最初のチュートリアルで説明したように、型指定された DataSet の DataTable はデータのリポジトリとして機能しますが、TableAdapters はデータベースと通信して基になるデータを取得および変更するためのラッパーとして機能します。 TableAdapters を使用すると、データベースの操作に伴う複雑さがカプセル化されるため、データベースに接続したり、コマンドを発行したり、DataTable に結果を追加したりするコードを記述する必要がありません。

ただし、TableAdapter の奥深くに潜り込んで、ADO.NET オブジェクトを直接操作するコードを書く必要がある場合もあります。 たとえば、トランザクション内のデータベース変更をラップするのチュートリアルでは、ADO.NET トランザクションを開始、コミット、ロールバックするためのメソッドを TableAdapter に追加しました。 これらのメソッドでは、TableAdapter の SqlCommand オブジェクトに割り当てられた、手動で作成された内部の SqlTransaction オブジェクトが使用されました。

このチュートリアルでは、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 クラスを使用します。 データベースに対して INSERTUPDATEDELETESELECT のいずれかのコマンドを発行するには、SqlCommand クラスを使用します。

トランザクション内のデータベース変更をラップするのチュートリアルを除き、TableAdapter の自動生成コードには、データベースへの接続、コマンドの発行、データの取得、そのデータの DataTables への追加に必要な機能が含まれているため、低レベルの ADO.NET コードを自分で記述する必要はありません。 ただし、これらの低レベルの設定をカスタマイズする必要がある場合もあります。 次のいくつかの手順では、TableAdapter によって内部的に使用される ADO.NET オブジェクトを活用する方法について説明します。

手順 1: Connection プロパティを使用して調べる

各 TableAdapter クラスには、データベース接続情報を指定する Connection プロパティがあります。 このプロパティのデータ型と ConnectionString 値は、TableAdapter 構成ウィザードで選択した内容によって決まります。 このウィザードで最初に TableAdapter を型指定された DataSet に追加するときに、データベース ソースを尋ねられたことを思い出してください (図 1 を参照)。 この最初の手順のドロップダウン リストには、構成ファイルで指定されたデータベースと、サーバー エクスプローラーのデータ接続内の他のデータベースが含まれます。 使用するデータベースがドロップダウン リストに存在しない場合は、[新しい接続] ボタンをクリックして必要な接続情報を指定して、新しいデータベース接続を指定できます。

The First Step of the TableAdapter Configuration Wizard

図 1: TableAdapter 構成ウィザードの最初の手順 (クリックするとフルサイズの画像が表示されます)

TableAdapter の Connection プロパティのコードを調べてみましょう。 データ アクセス層を作成するのチュートリアルで説明したように、自動生成された TableAdapter コードを表示するには、[クラス ビュー] ウィンドウに移動し、適切なクラスにドリルダウンして、メンバー名をダブルクリックします。

[表示] メニューに移動し、[クラス ビュー] を選択して (または Ctrl + Shift + C キーを押して) [クラス ビュー] ウィンドウに移動します。 [クラス ビュー] ウィンドウの上半分から NorthwindTableAdapters 名前空間までドリル ダウンし、ProductsTableAdapter クラスを選びます。 これにより、図 2 に示すように、クラス ビューの下半分に ProductsTableAdapter のメンバーが表示されます。 Connection プロパティをダブルクリックすると、そのコードが表示されます。

Double-Click the Connection Property in the Class View to View Its Auto-Generated Code

図 2: クラス ビューで Connection プロパティをダブルクリックして自動生成されたコードを表示する

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 クラスがインスタンス化されると、メンバー変数 _connectionnull と等しくなります。 Connection プロパティにアクセスすると、最初に _connection メンバー変数がインスタンス化されているかどうかが確認されます。 されていない場合は、InitConnection メソッドが呼び出されます。これにより、_connection がインスタンス化され、その ConnectionString プロパティが TableAdapter 構成ウィザードの最初の手順で指定された接続文字列値に設定されます。

Connection プロパティは、SqlConnection オブジェクトに割り当てることもできます。 これを行うと、新しい SqlConnection オブジェクトが TableAdapter の各 SqlCommand オブジェクトに関連付けられます。

手順 2: 接続レベル設定を公開する

接続情報は TableAdapter 内にカプセル化されたままにし、アプリケーション アーキテクチャ内の他のレイヤーからアクセスできないようにする必要があります。 ただし、TableAdapter の接続レベルの情報をクエリ、ユーザー、または ASP.NET ページでアクセスまたはカスタマイズできるようにする必要があるシナリオもあります。

Northwind DataSet の ProductsTableAdapter を拡張して、ConnectionString プロパティを含めましょう。これは、TableAdapter で使用される接続文字列をビジネス ロジック レイヤーが読み取ったり変更したりするために使用できます。

Note

"接続文字列" は、使用するプロバイダー、データベースの場所、認証資格情報、その他のデータベース関連の設定など、データベース接続情報を指定する文字列です。 さまざまなデータ ストアおよびプロバイダーで使用される接続文字列パターンのリストについては、ConnectionStrings.com を参照してください。

データ アクセス層を作成するのチュートリアルで説明したように、型指定された DataSet の自動生成クラスは、部分クラスを使用して拡張できます。 まず、プロジェクトの ~/App_Code/DAL フォルダーの下に ConnectionAndCommandSettings という新しいサブフォルダーを作成します。

Add a Subfolder Named ConnectionAndCommandSettings

図 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;
            }
        }
    }
}

この部分クラスは、ConnectionString という public プロパティを ProductsTableAdapter クラスに追加します。これにより、任意のレイヤーが TableAdapter の基になる接続の接続文字列を読み取ったり更新したりできるようになります。

この部分クラスを作成 (および保存) したら、ProductsBLL クラスを開きます。 既存のメソッドのいずれかに移動して「Adapter」と入力し、ピリオド キーを押して IntelliSense を起動します。 IntelliSense で新しい ConnectionString プロパティが使用可能になっていることがわかります。これは、BLL からこの値をプログラムで読み取ったり調整したりできることを意味します。

接続オブジェクト全体の公開

この部分クラスは、基になる接続オブジェクトの 1 つのプロパティ (ConnectionString) のみを公開します。 接続オブジェクト全体を TableAdapter の範囲を超えて使用できるようにするには、代わりに Connection プロパティの保護レベルを変更できます。 手順 1 で調べた自動生成コードでは、TableAdapter の Connection プロパティが internal としてマークされていることがわかりました。これは、同じアセンブリ内のクラスからのみアクセスできることを意味します。 ただし、これは TableAdapter の ConnectionModifier プロパティを使用して変更できます。

Northwind DataSet を開き、デザイナーで [ProductsTableAdapter] をクリックして、プロパティ ウィンドウに移動します。 そこで、ConnectionModifier が既定値の Assembly に設定されていることがわかります。 Connection プロパティを型指定された DataSet のアセンブリの外部で使用できるようにするには、ConnectionModifier プロパティを Public に変更します。

The Connection Property s Accessibility Level Can Be Configured via the ConnectionModifier Property

図 4: Connection プロパティのアクセシビリティ レベルは、ConnectionModifier プロパティを使用して構成できます (クリックするとフルサイズの画像が表示されます)

DataSet を保存し、ProductsBLL クラスに戻ります。 前と同様に、既存のメソッドのいずれかに移動し、「Adapter」と入力し、ピリオド キーを押して IntelliSense を起動します。 このリストには Connection プロパティが含まれているため、BLL から任意の接続レベルの設定をプログラムで読み取ったり割り当てたりすることができるようになりました。

TableAdapter は、既定で自動生成された INSERTUPDATEDELETE の各ステートメントを持つメイン クエリで構成されます。 このメイン クエリの INSERTUPDATEDELETE の各ステートメントは、Adapter プロパティを介して ADO.NET データ アダプター オブジェクトとして TableAdapter のコードに実装されます。 Connection プロパティと同様に、Adapter プロパティのデータ型は、使用するデータ プロバイダーによって決まります。 これらのチュートリアルでは SqlClient プロバイダーを使用するため、Adapter プロパティは SqlDataAdapter 型です。

TableAdapter の Adapter プロパティには、INSERTUPDATEDELETE の各ステートメントを発行するために使用する SqlCommand 型の次の 3 つのプロパティがあります。

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

SqlCommand オブジェクトは、データベースに特定のクエリを送信する役割を担い、CommandText (実行するアドホック SQL ステートメントまたはストアド プロシージャを含む) や Parameters (SqlParameter オブジェクトのコレクション) のようなプロパティを持ちます。 データ アクセス層を作成するのチュートリアルで説明したように、これらのコマンド オブジェクトは、プロパティ ウィンドウでカスタマイズできます。

TableAdapter には、メイン クエリに加えて、呼び出されたときに指定されたコマンドをデータベースにディスパッチする可変数のメソッドを含めることができます。 メイン クエリのコマンド オブジェクトと追加のすべてのメソッドのコマンド オブジェクトは、TableAdapter の CommandCollection プロパティに格納されます。

ここで、ProductsTableAdapter DataSet の Northwind によって生成された、これら 2 つのプロパティと、それらをサポートするメンバー変数およびヘルパー メソッドのコードを見てみましょう。

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: コマンド レベルの設定を公開する

コマンド レベルの情報は、データ アクセス層内にカプセル化されたままにしておくのが理想的です。 ただし、この情報がアーキテクチャの他のレイヤーで必要な場合は、接続レベルの設定と同様に、部分クラスを介して公開できます。

TableAdapter には 1 つの Connection プロパティしかないため、接続レベルの設定を公開するためのコードは非常に簡単です。 TableAdapter には複数のコマンド オブジェクト (InsertCommandUpdateCommandDeleteCommand) と、CommandCollection プロパティ内の可変数のコマンド オブジェクトがあるため、コマンド レベルの設定を変更する場合はもう少し複雑になります。 コマンド レベルの設定を更新するときは、これらの設定をすべてのコマンド オブジェクトに反映する必要があります。

たとえば、実行に非常に長い時間がかかった特定のクエリが TableAdapter にあるとします。 TableAdapter を使用してこれらのクエリの 1 つを実行する場合は、コマンド オブジェクトの CommandTimeout プロパティを増やす必要がある場合があります。 このプロパティは、コマンドの実行を待機する秒数を指定します。既定値は 30 です。

BLL によって CommandTimeout プロパティを調整できるようにするには、手順 2 で作成した部分クラス ファイル (ProductsTableAdapter.ConnectionAndCommandSettings.cs) を使用して、次の public メソッドを ProductsDataTable に追加します。

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 インスタンスによって発行されるすべてのコマンドのコマンド タイムアウトを設定できます。

Note

Adapter および CommandCollection のプロパティは private としてマークされているため、TableAdapter 内のコードからのみアクセスできます。 Connection プロパティとは異なり、これらのアクセス修飾子は構成できません。 そのため、アーキテクチャ内の他のレイヤーにコマンド レベルのプロパティを公開する必要がある場合は、上記の部分クラスのアプローチを使用して、private コマンド オブジェクトの読み取りまたは書き込みを行う public メソッドまたはプロパティを提供する必要があります。

まとめ

型指定された DataSet 内の TableAdapters は、データ アクセスの詳細と複雑さをカプセル化するために機能します。 TableAdapter を使用すると、データベースに接続したり、コマンドを発行したり、DataTable に結果を追加したりするために ADO.NET コードを記述する必要がありません。 すべて自動的に処理されます。

ただし、接続文字列や既定の接続またはコマンドのタイムアウト値を変更するなど、低レベルの ADO.NET の詳細をカスタマイズする必要がある場合があります。 TableAdapter には、自動生成された ConnectionAdapterCommandCollection の各プロパティがありますが、これらは既定では internal または private のいずれかです。 この内部情報を公開するには、部分クラスを使用して TableAdapter を拡張し、public メソッドまたはプロパティを含めます。 または、TableAdapter の Connection プロパティ アクセス修飾子を、TableAdapter の ConnectionModifier プロパティを通じて構成できます。

プログラミングに満足!

著者について

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

特別な感謝

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