次の方法で共有


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

スコット・ミッチェル著

PDF をダウンロードする

型指定された 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 専用に設計および最適化されているため、はるかに効率的です。

プログラムによってデータにアクセスする場合、次のパターンが一般的に使用されます。

  1. データベースへの接続を確立します。
  2. コマンドを発行します。
  3. SELECTクエリの場合は、結果のレコードを操作します。

これらの各手順を実行するための個別の ADO.NET クラスがあります。 たとえば、SqlClient プロバイダーを使用してデータベースに接続するには、 SqlConnection クラスを使用します。 データベースに INSERTUPDATEDELETE、または SELECT コマンドを発行するには、 SqlCommand クラスを使用します。

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

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

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

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

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

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

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

 クラス ビューで Connection プロパティをDouble-Click して自動生成されたコードを表示する

図 2: クラス ビューの Connection プロパティを Double-Click して自動生成されたコードを表示する

TableAdapter の Connection プロパティとその他の接続関連のコードは次のとおりです。

Private _connection As System.Data.SqlClient.SqlConnection
Private Sub InitConnection()
    Me._connection = New System.Data.SqlClient.SqlConnection
    Me._connection.ConnectionString = _
        ConfigurationManager.ConnectionStrings("NORTHWNDConnectionString").ConnectionString
End Sub
Friend Property Connection() As System.Data.SqlClient.SqlConnection
    Get
        If (Me._connection Is Nothing) Then
            Me.InitConnection
        End If
        Return Me._connection
    End Get
    Set
        Me._connection = value
        If (Not (Me.Adapter.InsertCommand) Is Nothing) Then
            Me.Adapter.InsertCommand.Connection = value
        End If
        If (Not (Me.Adapter.DeleteCommand) Is Nothing) Then
            Me.Adapter.DeleteCommand.Connection = value
        End If
        If (Not (Me.Adapter.UpdateCommand) Is Nothing) Then
            Me.Adapter.UpdateCommand.Connection = value
        End If
        Dim i As Integer = 0
        Do While (i < Me.CommandCollection.Length)
            If (Not (Me.CommandCollection(i)) Is Nothing) Then
                CType(Me.CommandCollection(i), _
                    System.Data.SqlClient.SqlCommand).Connection = value
            End If
            i = (i + 1)
        Loop
    End Set
End Property

TableAdapter クラスがインスタンス化されると、 _connection メンバー変数は Nothingと等しくなります。 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 という名前の新しいサブフォルダーを作成します。

ConnectionAndCommandSettings という名前のサブフォルダーを追加する

図 3: 名前付きのサブフォルダーを追加する ConnectionAndCommandSettings

ProductsTableAdapter.ConnectionAndCommandSettings.vbという名前の新しいクラス ファイルを追加し、次のコードを入力します。

Namespace NorthwindTableAdapters
    Partial Public Class ProductsTableAdapter
        Public Property ConnectionString() As String
            Get
                Return Me.Connection.ConnectionString
            End Get
            Set(ByVal value As String)
                Me.Connection.ConnectionString = value
            End Set
        End Property
    End Class
End Namespace

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

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

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

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

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

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 プロパティには、SqlCommandINSERT、およびUPDATEステートメントを発行するために使用する、DELETE型の 3 つのプロパティがあります。

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

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

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

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

Private WithEvents _adapter As System.Data.SqlClient.SqlDataAdapter
Private Sub InitAdapter()
    Me._adapter = New System.Data.SqlClient.SqlDataAdapter
    
    ... Code that creates the InsertCommand, UpdateCommand, ...
    ... and DeleteCommand instances - omitted for brevity ...
End Sub
Private ReadOnly Property Adapter() As System.Data.SqlClient.SqlDataAdapter
    Get
        If (Me._adapter Is Nothing) Then
            Me.InitAdapter
        End If
        Return Me._adapter
    End Get
End Property
Private _commandCollection() As System.Data.SqlClient.SqlCommand
Private Sub InitCommandCollection()
    Me._commandCollection = New System.Data.SqlClient.SqlCommand(8) {}
    ... Code that creates the command objects for the main query and the ...
    ... ProductsTableAdapter�s other eight methods - omitted for brevity ...
End Sub
Protected ReadOnly Property CommandCollection() As System.Data.SqlClient.SqlCommand()
    Get
        If (Me._commandCollection Is Nothing) Then
            Me.InitCommandCollection
        End If
        Return Me._commandCollection
    End Get
End Property

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

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

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

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

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

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

Public Sub SetCommandTimeout(ByVal timeout As Integer)
    If Me.Adapter.InsertCommand IsNot Nothing Then
        Me.Adapter.InsertCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.DeleteCommand IsNot Nothing Then
        Me.Adapter.DeleteCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.UpdateCommand IsNot Nothing Then
        Me.Adapter.UpdateCommand.CommandTimeout = timeout
    End If
    For i As Integer = 0 To Me.CommandCollection.Length - 1
        If Me.CommandCollection(i) IsNot Nothing Then
            Me.CommandCollection(i).CommandTimeout = timeout
        End If
    Next
End Sub

このメソッドは、BLL またはプレゼンテーション レイヤーから呼び出して、その TableAdapter インスタンスによって発生するすべてのコマンドのタイムアウトを設定できます。

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

概要

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

ただし、接続文字列の変更や既定の接続またはコマンドのタイムアウト値など、低レベルの ADO.NET の詳細をカスタマイズする必要がある場合があります。 TableAdapter には自動生成された ConnectionAdapter、および CommandCollection のプロパティがありますが、これらは既定で Friend または 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にメッセージを送ってください。