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

作成者: Scott Mitchell

PDF のダウンロード

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

はじめに

チュートリアル シリーズ全体を通じて、Typed DataSets を使用して、階層化されたアーキテクチャのデータ アクセス層とビジネス オブジェクトを実装しました。 最初のチュートリアルで説明したように、型指定された 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。 、、UPDATEDELETE、または SELECT コマンドをINSERTデータベースに発行するには、 クラスを使用しますSqlCommand

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

手順 1: Connection プロパティを使用した検査

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

TableAdapter 構成ウィザードの最初の手順

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

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

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

クラス ビューで 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 メソッドが呼び出され、そのConnectionStringプロパティがインスタンス化_connectionされ、TableAdapter 構成ウィザードの最初の手順で指定された接続文字列値に設定されます。

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

手順 2: Connection-Level 設定を公開する

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

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

注意

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

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

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

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

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

接続オブジェクト全体を公開する

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

DataSet をNorthwind開き、Designerの をProductsTableAdapterクリックして、プロパティ ウィンドウに移動します。 ここでは、既定値 Assemblyに設定されている ConnectionModifier が表示されます。 型指定された DataSet アセンブリの外部でプロパティを使用できるようにするには Connection 、 プロパティを ConnectionModifierPublic変更します。

Connection プロパティのアクセシビリティ レベルは ConnectionModifier プロパティを使用して構成できます

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

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

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

TableAdapter の Adapter プロパティには、および DELETE ステートメントを発行するために使用する型SqlCommandINSERTUPDATE3 つのプロパティがあります。

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

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

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

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

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

プロパティと CommandCollection プロパティのAdapterコードは、 プロパティのConnectionコードとよく似たコードです。 プロパティで使用されるオブジェクトを保持するメンバー変数があります。 プロパティ get アクセサーは、対応するメンバー変数 nullが かどうかを確認することから始めます。 その場合は、メンバー変数のインスタンスを作成し、コア コマンド関連のプロパティを割り当てる初期化メソッドが呼び出されます。

手順 4: Command-Level 設定を公開する

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

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

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

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

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

まとめ

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

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

プログラミングに満足!

著者について

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

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、バーナデット リー、S レン ジェイコブ ラウリッセン、テレサ マーフィー、ヒルトン ガイゼナウでした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。