• 検索結果がありません。

データアダプタ概要

N/A
N/A
Protected

Academic year: 2021

シェア "データアダプタ概要"

Copied!
30
0
0

読み込み中.... (全文を見る)

全文

(1)

■ データアダプタ ■ ■ データアダプタの概要 データアダプタは、ADO.NET マネージプロバイダの重要な部分で有り、データソースとデータセット の間の通信に使用されるオブジェクトのセットで有る。マネージプロバイダには、アダプタの他に接続 オブジェクト、データリーダーオブジェクト、及び、コマンドオブジェクトが含まれる。アダプタは、 データソースとデータセットの間でデータを交換する為に使用される。多くのアプリケーションでは、 此れはデータベースからデータセットにデータを読み取って、変更されたデータをデータセットからデ ータベースに書き込む事を意味する。併し、データアダプタは任意のソースとデータセットの間でデー タを移動出来る。例えば、Microsoft Exchange サーバーとデータセットの間でデータを移動するアダプ タも考えられる。 ※ 以前のバージョンの Visual Studio では、アプリケーションとデータベースの通信にデータアダプタ が使用されて居た。データアダプタは現在も.NET Framework データプロバイダの主要なコンポー ネントだが、TableAdapter はデザイナで生成されるコンポーネントで、アプリケーションとデータ ベースの間でデータを移動する処理を簡略化する。TableAdapter の操作方法の詳細に付いては、 「TableAdapter の概要」を参照され度い。 一般に、アダプタはデータセットとの間で何の様なデータを交換するかを指定出来る様に構成出来る。 此れは多くの場合、データベースの読み取りや書き込みする時に呼び出される SQL ステートメントや ストアドプロシージャへの参照と謂う形を取る。 Visual Studio に依って、此等のデータアダプタがデータベースで使用出来る様に成る。 ・OleDbDataAdapter オブジェクトは、OLE DB プロバイダに依って公開される任意のデータソース と共に使用するのに適して居る。 ・SqlDataAdapter オブジェクトは、SQL Server に固有のオブジェクトで有る。此のオブジェクトは OLE DB 層を経由する必要が無い為、OleDbDataAdapter クラスよりも高速で有る。但し、SQL Server 7.0 以降丈で使用出来る。 ・OdbcDataAdapter オブジェクトは、ODBC データソースへのアクセス向けに最適化されて居る。 ・OracleDataAdapter オブジェクトは、Oracle データベースへのアクセス向けに最適化されて居る。 ※ データアダプタ、データ接続、データコマンド、データリーダーは、.NET Framework データプロ バイダを構成するコンポーネントで有る。Microsoft やサードパーティプロバイダには、Visual Studio に統合出来る其の他の.NET Framework データプロバイダが用意されて居る。他の.NET Framework データプロバイダの詳細に付いては、「.NET Framework データプロバイダ」を参照さ れ度い。

アダプタの作成や操作には、.NET Framework マネージプロバイダの名前空間の一部で有る以下の名前 空間を使用出来る。

(2)

SqlClient マネージプロバイダ名前空間 OleDb マネージプロバイダ名前空間 一般に、各データアダプタは、1 つのデータソーステーブルとデータセット内の 1 つの DataTable オブ ジェクトとの間でデータを交換する。データセットに複数のデータテーブルが含まれる場合、通常の方 法と仕ては、複数のデータアダプタからデータセットにデータを供給し、其のデータを夫々れのデータ ソーステーブルに書き戻す。 データセットにテーブルを作成する場合は、アダプタのメソッドを呼び出して SQL ステートメントや ストアドプロシージャを実行する。アダプタに依ってデータリーダーオブジェクト(SqlDataReader、 OleDbDataReader、OdbcDataReader、又は、OracleDataReader)が作成され、データがデータセッ トに読み取られる。 ※ データベースからデータを読み取る時にデータをデータセットに格納する必要が無い為、読み取り 専用データを扱う時に使用すると効率的で有る。詳細に付いては、後の「読み取り専用データ」を 参照され度い。亦、SQL ステートメントを使用してデータセットを作成しなくても、直接 SQL ス テートメントを実行出来る。詳細に付いては、「コマンドの使用」を参照され度い。 同様に、データベースを更新する場合は、適切な SQL ステートメントやストアドプロシージャを呼び 出すアダプタのメソッドを呼び出して、データベースに実際の更新を行う。 データアダプタ、及び、関連するテーブル データセット内に個別のテーブルを持つと謂う事は、データアダプタが一般に、テーブルを結合する SQL コマンドやストアドプロシージャを参照しない事を意味する。其の代わりに、関連する各テーブル からの情報は異なるアダプタに依って個別にデータセットに読み込まれる。此の時、DataRelation オ ブジェクトは、データセットテーブル間の制約(例えば、連鎖更新等)を管理し、関連するマスターレ コードと子レコードの間で移動出来る様にする為に使用される。

例えば、Northwind と謂うデータベース内で 2 つの関連するテーブル Customers と Orders を使用す るとする。結合を指定して2 つのテーブルを 1 つの結果セットに纏める代わりに、通常は 2 つのアダプ

(3)

タを定義する。1 つはデータセット内に Customers テーブルを作成し、今 1 つは Order レコードを別 のデータセットテーブルに読み込む。多くの場合、此等の各アダプタには、データテーブル内のレコー ド数を制限する為の選択基準が含まれる。

亦、Order レコードが CustomerID フィールドに基づいて Customer レコードに関連付けられる事を指 定する様に、データセット内でDataRelation オブジェクトを定義する。テーブルを引き続き個別に管 理出来るが、データソースからレコードをフェッチする前にテーブルを結合した場合は、テーブルを個 別に管理出来ない。関連するレコードを使用する場合は、DataRelation オブジェクトのプロパティや メソッドを呼び出す事が出来る。 データリレーションシップの詳細に付いては、「データセットのリレーションシップ」を参照され度い。 接続オブジェクト データアダプタでデータを読み書きするには、データソースへの接続が確立されて居る必要が有る。其 の 為 、 ア ダ プ タ は 、 接 続 オ ブ ジ ェ ク ト (SqlConnection、OleDbConnection、OdbcConnection、 OracleConnection)を使用してデータソースに接続する。アダプタには、最大 4 つ迄の接続参照を含め る事が出来る。此れは、アダプタが実行する4 種類のアクション(選択、更新、挿入、削除)に対応す る。 ツールボックスの [データ] タブに有る接続オブジェクトの一覧を次の表に示す。 接続オブジェクト 説明 SqlConnection SQL Server 7.0 以降のデータベースへの接続 OleDbConnection OLE DB データソースへの接続 OdbcConnection ODBC データソースへの接続 OracleConnection Oracle データベースへの接続 孰れの場合も、接続オブジェクトは、データソース内の固有のセッションを表す。総ての接続オブジェ クトには、接続の詳細(ユーザーID、パスワード、接続タイムアウト設定等)を設定、変更する為のプ ロパティが用意されて居る。亦、データベーストランザクションを開始、コミット、ロールバックする 為のメソッドも有る。接続オブジェクトの詳細に付いては、「データソースへの接続」を参照され度い。 セキュリティに関するメモ:機密情報(サーバー名、ユーザー名、パスワード等)を格納すると、アプ リケーションのセキュリティに影響を及ぼす事が有る。データベースへのアクセスを制御する方法と仕 ては、Windows オートメーション(統合セキュリティとも呼ばれる)を使用する方が安全で有る。 ADO.NET コマンドオブジェクト アダプタを使用して、データソース内のレコードの読み取り、追加、更新、削除が可能で有る。各操作 を何の様に行うかを指定する為に、アダプタは次の4 つのプロパティをサポートして居る。 ・SelectCommand:データストアから行を取得するコマンドの参照。 ・InsertCommand:データストアに行を挿入するコマンドの参照。 ・UpdateCommand:データストアの行を変更するコマンドの参照。 ・DeleteCommand:データストアから行を削除するコマンドの参照。 ※ コマンドとは、SQL ステートメントやストアドプロシージャ名を謂う。 プ ロ パ テ ィ 自 体 は 、 オ ブ ジ ェ ク ト で 有 る 。 プ ロ パ テ ィ は 、SqlCommand 、 OleDbCommand 、 OdbcCommand、又は、OracleCommand の孰れかのクラスのインスタンスで有る。此等のオブジェク トは、SQL ステートメントやストアドプロシージャへの参照を含む CommandText プロパティをサポ ートして居る。

(4)

※ コマンドクラスは、接続クラスと一致する必要が有る。例えば、SqlConnection オブジェクトを使 用してSQL Server と通信して居る場合は、SqlCommand クラスから派生したコマンドを使用する 必要が有る。

コマンドオブジェクトのテキストは明示的に設定出来るが、必ずしも設定する必要は無い。多くの場合 は、Visual Studio に依って必要な SQL ステートメントが生成される。亦、UpdateCommand、 InsertCommand、又は、DeleteCommand オブジェクトが指定されて居ない場合は、実行時にアダプ タが適切なSQL ステートメントを自動的に生成する。詳細に付いては、「コマンドの自動生成」を参照 され度い。 但し、デザイン時や実行時にコマンドオブジェクトを操作する事で、コマンドの実行をより直接的に制 御出来る。例えば、SelectCommand オブジェクトに関連付けられたコマンドを実行の直前に作成した り変更したり出来る。 データアダプタに依存せずに、コマンドを自分で実行する事も出来る。此れに依り、データベース定義 の設定や変更に使用するコマンド等、任意のSQL コマンドをデータアダプタを通して渡す事が出来る。 亦、レコードセットを返さないストアドプロシージャを直接呼び出す事も出来る。例えば、データベー スに対してユーザーの入力が適切か何うかを確認するストアドプロシージャ等で有る。詳細に付いては、 「コマンドの実行」を参照され度い。 セキュリティに関するメモ:CommandType プロパティを Text に設定したデータコマンドを使用する 時は、クライアントから送信された情報をデータベースに渡す前に、其の情報を充分にチェックする必 要が有る。悪意の有るユーザーが、承認無しでデータベースにアクセスしたり、データベースを破壊し たりする目的で、変更したSQL ステートメントや追加の SQL ステートメントの送信(埋め込み)を試 みる場合が有る。ユーザーの入力をデータベースに転送する前に、其の情報が有効で有る事を常に検証 する必要が有る。出来る限り、常にパラメータ化されたクエリやストアドプロシージャを使用する事を 推奨する。詳細に付いては、「スクリプトによる攻略の概要」を参照され度い。 コマンドパラメータ 通常、データアダプタ内のコマンドは、パラメータドリブンで有る。例えば、SelectCommand プロパ ティに対するコマンドは、多くの場合、WHERE 句にパラメータを持ち、データベースから何のレコー ドを取得するかを実行時に指定出来る様に成って居る。其他のコマンドでは、パラメータを使用して、 レコードに書き込むデータや、データベース内の何のレコードを更新するか等の情報を実行時に渡す事 が出来る。データアダプタでのパラメータの使い方の詳細に付いては、「データアダプタコマンドのパ ラメータ」を参照され度い。 データアダプタに依る読み取りと更新 データアダプタの主要な目的は、データストアとデータセットの間でデータを交換する事で有る。アダ プタは、此の両者の間でデータを移動する為に固有のメソッドをサポートして居る。 ※ データを読み取る丈で更新しない場合には、データをデータセットに格納する必要は無い。其の代 わりに、データベースからアプリケーションに直接読み込む事が出来る。詳細に付いては、後の「読 み取り専用データ」を参照され度い。 データアダプタを使用して次の事が出来る。 ・データストアの行をデータセット内の対応するデータテーブルに取得する。 行 を デ ー タ セ ッ ト に 取 得 す る に は 、 デ ー タ ア ダ プ タ オ ブ ジ ェ ク ト (SqlDataAdapter 、 OleDbDataAdapter、OdbcDataAdapter、又は、OracleDataAdapter)に対して Fill メソッドを使 用する。Fill メソッドを呼び出すと、データストアに SQL SELECT ステートメントが送信される。

(5)

・データセットテーブルに加えられた変更を対応するデータストアに送信する。 データセットのデータセットテーブルをデータストアに送信するには、アダプタのUpdate メソッド を使用する。此のメソッドを呼び出すと、対象のレコードを新しく作成するか、変更するか、削除す るかに応じて、必要なSQL INSERT、UPDATE、又は、DELETE ステートメントが実行される。 データアダプタを使用して更新を実行する方法の詳細に付いては、「DataAdapter に依るデータソー スの更新」を参照され度い。 読み取り専用データ クエリ結果を使用して逐次読み取り専用でデータを渡す必要が有る場合は、データセットを設定する代 わりに、データリーダーオブジェクトを使用出来る。データリーダーオブジェクトは、データソースか らデータをフェッチし、直接アプリケーションに渡す。一般に、データリーダーオブジェクトは、デー タをデータセットにキャッシュする必要が無い時に、データに対して読み取り専用で前方而巳のアクセ スを行う為に使用される。但し、データアダプタ自体は、データセットにデータを格納する時にデータ リーダーオブジェクトを使用する。読み取り専用アクセスの例と仕ては、データベース情報を表示する Web フォームページが有る。Web フォームページはラウンドトリップ毎に再作成される為、多くの場 合、データをデータセットに格納しても意味が無い。

Visual Studio には、4 つのデータリーダーオブジェクト(SqlDataReader、OleDbDataReader、 OdbcDataReader、OracleDataReader)が用意されて居る。読み取り専用アクセスを効率良く実行す る為のデータリーダーオブジェクトの使い方の詳細に付いては、「DataReader の使用」を参照され度い。 テーブル割り当て Visual Studio ツールを使用してデータベーステーブルからデータセットを生成した場合、既定では、 データセット内のテーブル名と列名がデータベース内の名前と同じに成る。併し、此れでは都合が悪い 場合も有る。例えば、データベースで使用されて居る名前が簡潔、又は、冗長過ぎる場合や、名前が外 国語で表記されて居る場合等で有る。亦、既存のスキーマで作業して居る場合は、スキーマで定義され た名前がデータベースで使用されて居る名前と一致しない事も有る。 従って、データベース内の名前とデータセット内の名前が一致して居る必要は無い。其の代わりに、デ ータセットコマンドで新しいテーブル名や列名を作成して、データベースで使用されて居る名前に関連 付ける事が出来る。アダプタは、TableMappings コレクションを使用して、データセットの構造(デー タテーブルやデータ列)とデータストアの構造(テーブルや列)との間の対応を維持する。テーブル割 り当ての詳細に付いては、後の「データアダプタでのテーブル割り当て」を参照され度い。 ■ データアダプタでのテーブル割り当て データアダプタがデータソースからデータを読み取る場合は、テーブル割り当てを使用して、対応する データセットテーブルの何処にデータを格納するかを決定する。此の割り当ては、ソース内の列の名前 をデータセットテーブル内の列の名前にリンクして居る。例えば、データソース内のau_id と謂う列の 情報がデータセットテーブル内のauthor_id_number と謂う列に属して居る様な場合が考えられる。 ※ 以前のバージョンの Visual Studio では、アプリケーションとデータベースの通信にデータアダプタ が使用されて居た。データアダプタは現在も.NET Framework データプロバイダの主要なコンポー ネントだが、TableAdapter はデザイナで生成されるコンポーネントで、アプリケーションとデータ ベースの間でデータを移動する処理を簡略化する。TableAdapter の操作方法の詳細に付いては、 「TableAdapter の概要」を参照され度い。 Visual Studio ツールを使用してデータソースの情報からデータセットを生成した場合、既定では、デ

(6)

ータセットの要素の名前は、データソースでの名前と同じに成る。但し、下記の様に、データソース内 の名前とデータセット内の名前が一致しない場合も有る。 ・異なる名前を使用する既存のスキーマからデータセットが生成された場合。 ・使い易さ、読み易さ、外国語との間の変換、又は、其他の理由から、データセット内のデータ要素名 を変更する必要が有る場合。 ・アダプタからデータセットを生成する時に、型指定されたデータメンバの名前を制御する場合。 テーブル割り当ての構造 テ ー ブ ル 割 り 当 て は 、 ア ダ プ タ の TableMappings プ ロ パ テ ィ に 依 っ て 確 立 さ れ る 。 此 れ は DataTableMapping 型の項目のコレクションで有る。割り当てるテーブルのセット夫々れに付いて、1 つのDataTableMapping オブジェクトが有る。通常、アダプタは 1 つのソーステーブルと 1 つのデー タセットテーブル丈に関連付けられる為、此の項目は1 つしか無い。但し、ストアドプロシージャは複 数の行セットを返す場合が有る。其の場合、2 番目以降のテーブルは TableMappings コレクションの 2 番目以降の割り当てを使用して割り当てられる。 夫々れの割り当て項目には、データソーステーブルやデータセットテーブルを識別するプロパティ、及 び、実際の割り当てを表す項目を含むColumnMappings プロパティが含まれる。 テーブル割り当ての動作 データアダプタのFill メソッドを呼び出すと、アダプタは、以下のプロセスを実行して、データセット 内の何処にデータを書き込むかを決定する。 1.TableMappings オブジェクト内で各ソース列名を探す。 2.ソース列名が見付かれば、データセットテーブル内の対応する列の一致する(関連付けられた)名 前を取得する。 3.手順2 で取得した名前を使用して、ソース列のデータを対応するデータセット列に書き込む。 様々な条件に於いて、アダプタが上記のプロセスを実行出来ない場合が有る。主要な物は、下記の2 つ で有る。 ・ソース列に対して割り当てが見付からない場合。此の原因と仕ては、TableMappings プロパティに何 も定義されて居ないか、特定の列が割り当てられて居ない事が考えられる。 ・書き込む列が TableMappings プロパティに割り当てられて居るか何うかに関係無く、其の列がデー タセットのスキーマに定義されて居ない場合。 アダプタには、此の孰れかの状況に当て嵌る場合に何の様に処理するかを指定する為の2 つのプロパテ ィが用意されて居る。此等の状況が発生してもアダプタはデータセットにデータを格納出来る為、必ず しもエラーでは無い。 MissingMappingAction プロパティは、マップが見付からない場合にアダプタが何の様に処理するかを 指定する為に使用する。次の設定が可能で有る。 ・Passthrough:アダプタは、列のデータを同じ名前のデータセット列に格納する。同じ名前のデータ セット列が無い場合、動作は下記のMissingSchemaAction の設定に依存する。

(7)

・Ignore:適切に割り当てられて居ない列は、データセットに読み込まれない。 ・Error:エラーを発生させる。 MissingSchemaAction プロパティでは、アダプタがデータセットのスキーマに定義されて居ない列に データを書き込もうと仕た時の処理を指定する。次の値を使用出来る。 ・Add:テーブル、又は、列が、スキーマ、及び、データセットに追加される。 ・AddWithKey:テーブル、又は、列が、主キーに関する情報と共に、データセット、及び、スキーマ に追加される。 ・Ignore:データセットスキーマに表されて居ないテーブルや列はデータセットに追加されない。 ・Error:エラーを発生させる。 一般には、両方のプロパティを組み合わせて設定する事に依り、アプリケーション固有のニーズを満足 させる。MissingMappingAction プロパティを Passthrough に、MissingSchemaAction プロパティを Add に設定すると、データセットでテーブル名や列名が自動的にソースから複製される。 逆に、データセットスキーマが厳密に定義されたアプリケーションでは、エラーのチェックを指定出来 る。其の様な場合、データセット内の格納先の列を明確に定義せずにソースからデータを取得すると、 ビジネスルールの違反等のエラーに成る可能性が有る。 スキーマに明示的に定義したデータや TableMappings プロパティで割り当てられて居るデータ丈をデ ータセットに読み込む場合は、Ignore を指定する。此れは、データセット内で必要な数よりも多い列を 返すストアドプロシージャやSQL ステートメントをアダプタが呼び出す場合に便利で有る。 ■ データアダプタコマンドのパラメータ 多くの場合、SelectCommand、InsertCommand、UpdateCommand、DeleteCommand オブジェクト のCommandText プロパティに定義されるデータアダプタのコマンドには、パラメータが有る。実行時 に、パラメータを使用して、コマンドが表すSQL ステートメントやストアドプロシージャに値を渡す。 ※ 以前のバージョンの Visual Studio では、アプリケーションとデータベースの通信にデータアダプタ が使用されて居た。データアダプタは現在でも.NET Framework データプロバイダのメインコンポ ーネントだが、デザイナに依って生成されるコンポーネントで有るTableAdapter を使うと、アプリ ケーションとデータベース間でデータを遣り取りするプロセスは簡略化される。TableAdapter の操 作方法の詳細に付いては、「TableAdapter の概要」を参照され度い。 パラメータは2 つのコンテキストで使用される。 ・選択パラメータ:実際のアプリケーションでは、データベース内のデータのサブセット丈をフェッチ する事が頻繁に有る。其の為には、実行時に取得する選択基準のパラメータを持つ WHERE 句を含 む SQL ステートメントやストアドプロシージャを使用する。亦、レコードの更新や削除をする時に は、変更対象のレコードを指定するWHERE 句を使用する。WHERE 句で使用される値は、通常は 実行時に取得される。 ・更新パラメータ:既存のレコードを更新する場合、又は、新しいレコードを挿入する場合に、変更す るレコードや新しいレコードの列の値を実行時に確立する。亦、オプティミスティック同時実行制御 のチェック中に使用される値は、パラメータを使用して確立される。

(8)

※ Oracle では、SQL ステートメントやストアドプロシージャで名前付きパラメータを使用する場合、 パラメータ名の前にコロン( : )を付ける必要が有る。但し、コード内の他の場所に有る名前付き パラメータを参照する場合(Add を呼び出す場合等)には、名前付きパラメータの前にコロンは付 けない。データプロバイダが自動的にコロンを追加する。詳細に付いては、「OracleParameter クラ ス」を参照され度い。 選択パラメータ データセットに格納するレコードを選択する時は、多くの場合、WHERE 句にパラメータを含めて、フ ェッチするレコードを実行時に指定出来る様にする。例えば、ユーザーが特定のタイトルキーワードを Web ページに入力して本のデータベースを検索するとする。其れを可能にするには、次に示す様な SQL ステートメントをSelectCommand の CommandText プロパティと仕て指定する。パラメータはプレー スホルダ(疑問符:? )又は、名前付きパラメータ変数に依って示される。OleDbCommand オブジェ クトや OdbcCommand オブジェクトを使用したクエリのパラメータには、疑問符( ? )を使用する。 SqlCommand オブジェクトを使用したクエリには、アットマーク(@)で始まる名前付きパラメータを 使用する。OracleCommand オブジェクトの場合は、コロン( : )で始まる名前付きパラメータを使用 する。 プレースホルダを使用したクエリの例を次に示す(Access、MySQL 等の場合)。 SELECT BookId, Title, Author, Price from BOOKS

WHERE (Title LIKE ?)

SqlCommand 名前付きパラメータを使用するクエリの例を次に示す(SQL Server 7.0 以降の場合)。 SELECT BookId, Title, Author, Price from BOOKS

WHERE (Title LIKE @title)

OracleCommand 名前付きパラメータを使用するクエリの例を次に示す(Oracle の場合)。 SELECT BookId, Title, Author, Price from BOOKS

WHERE (Title LIKE :title)

アプリケーションで、ユーザーにタイトルキーワードの入力を要求する。然して、パラメータの値を設 定してコマンドを実行する。 ※ ルックアップテーブルを設定する場合等、データベーステーブル全体の内容を取得する必要が有る 場合も有る。併し一般には、アプリケーションの効率を高める為、必要なデータ丈をフェッチする。 Visual Studio では、クエリビルダを使用してパラメータを持つ SQL ステートメントを作成出来る。サ ーバーエクスプローラから要素をドラッグすると、可能な部分に付いては、Visual Studio に依って自 動的にパラメータが設定される。設定は手動で完成させる必要が有る。 更新パラメータ アダプタのSelectCommand オブジェクトにパラメータ化されたコマンドが含まれるか何うかに関係無 く、UpdateCommand、InsertCommand、DeleteCommand の各プロパティに対するコマンドには常 にパラメータが含まれる。 UpdateCommand プロパティや InsertCommand プロパティに対するコマンドでは、データベース内 で更新する総ての列に対してパラメータが必要で有る。亦、UpdateCommand ステートメントや DeleteCommand ステートメントでは、多くの SelectCommand オブジェクトと同様に、更新するレコ ードを識別する為のパラメータ化されたWHERE 句が必要で有る。

(9)

ユーザーが本を購入出来るアプリケーションを考えて観る事にする。ユーザーは、買い物をする間、買 い物籠を保持するが、此れは、データテーブルと仕て実装される。ShoppingCart テーブルに於いて、 ユーザーは購入する夫々れの本に対するレコードを保持する。此のレコードには、書籍ID と顧客 ID が 含まれ、買い物籠レコードのキーと仕て使用される。 ユーザーが買い物籠に本を追加すると、アプリケーションはSQL INSERT ステートメントを呼び出す。 アダプタでのステートメントの構文は次の様に成る。

INSERT INTO ShoppingCart (BookId, CustId, Quantity) Values (?, ?, ?)

3 つの疑問符( ? )は、顧客 ID、書籍 ID、及び、数量の値を実行時に取得するパラメータのプレース ホルダを示して居る。名前付きパラメータを使用して居る場合は、同じクエリが次の様に成る。

INSERT INTO ShoppingCart (BookId, CustId, Quantity)

Values (@bookid, @custid, @quantity)

ユーザーが買い物カゴ内の項目を変更する場合(例えば、数量の変更等)、アプリケーションは SQL UPDATE ステートメントを呼び出す。此のステートメントの構文は次の様に成る。

UPDATE ShoppingCart

SET (BookId = ?, CustId = ?, Quantity = ?) WHERE (BookId = ? AND CustId = ?)

亦、名前付きパラメータを使用して居る場合は次の様に成る。 UPDATE ShoppingCart

SET (BookId = @bookid, CustId = @custid, Quantity = @quantity) WHERE (BookId = @bookid AND CustId = @custid)

此のステートメントに於いて、SET 句のパラメータには変更するレコードの新しい値が入る。WHERE 句のパラメータは、何のレコードを更新するかを識別する物で有り、レコードの元の値が入る。 ユーザーは、買い物籠から項目を削除する事も出来る。其の場合、パラメータのプレースホルダを使用 して居る時は、アプリケーションは次の様な構文でSQL DELETE ステートメントを呼び出す。

DELETE FROM ShoppingCart WHERE (BookId = ? AND CustId = ?)

名前付きパラメータを使用して居る時は、次の様に成る。 DELETE FROM ShoppingCart

WHERE (BookId = @bookid AND CustId = @custid) パラメータコレクションとパラメータオブジェクト

実行時にパラメータの値を渡す事が出来る様に、データアダプタの4 つのコマンドオブジェクトは夫々 れParameters プロパティをサポートして居る。此のプロパティには、ステートメント内のプレースホ ルダと一対一で対応する各パラメータオブジェクトのコレクションが含まれる。

(10)

各データアダプタに対応するパラメータコレクションを次の表に示す。 データアダプタ パラメータコレクション SqlDataAdapter SqlParameterCollection OleDbDataAdapter OleDbParameterCollection OdbcDataAdapter OdbcParameterCollection OracleDataAdapter OracleParameterCollection ※ Oracle では、SQL ステートメントやストアドプロシージャで名前付きパラメータを使用する場合、 パラメータ名の前にコロン( : )を付ける必要が有る。但し、コード内の他の場所に有る名前付き パラメータを参照する場合(Add を呼び出す場合等)には、名前付きパラメータの前にコロンは付 けない。.NET Framework Oracle 用データプロバイダが自動的にコロンを追加する。

パラメータコレクションを使用する事で、実行時の値に依って SQL コマンドの文字列を手動で構築す る手間が省け、更に、パラメータで型チェックが出来ると謂う利点も有る。

データアダプタ構成ウィザードを使用してアダプタを設定する場合は、4 つのアダプタコマンド総てに 対してパラメータコレクションが自動的にセットアップされ、設定される。サーバーエクスプローラか らフォームやコンポーネントに要素をドラッグすると、Visual Studio は以下の設定を実行する。 ・デザイナにテーブルや列をドラッグした場合、Visual Studio はパラメータの無い SelectCommand

オブジェクト(詰まり、SQL SELECT ステートメント)と、パラメータ化された UpdateCommand、 InsertCommand、DeleteCommand の各オブジェクトを生成する。SelectCommand オブジェクトス テートメントにパラメータを含める場合は、手動で設定出来る。 ・デザイナにストアドプロシージャをドラッグした場合、Visual Studio は、ストアドプロシージャの 必要に応じてパラメータを持つSelectCommand オブジェクトを生成する。但し、UpdateCommand、 InsertCommand、DeleteCommand の各オブジェクトが必要な場合は、各オブジェクトをパラメー タと共に自分で設定する必要が有る。 一般に、アダプタに対してパラメータ化されたクエリを作成する場合は、データアダプタ構成ウィザー ドを使用する。但し、必要な場合は [プロパティ] ウィンドウを使用してパラメータを手動で設定する 事も出来る。 パラメータコレクションの構造 コマンドパラメータコレクション内の項目は、対応するコマンドオブジェクトに必要なパラメータと一 対一で対応して居る。コマンドオブジェクトが SQL ステートメントで有る場合、コレクション内の項 目はステートメント内のプレースホルダ(疑問符:? )に対応する。次の UPDATE ステートメントに は、5 つのパラメータ項目のコレクションが必要で有る。 UPDATE ShoppingCart

SET (BookId = ?, CustId = ?, Quantity = ?) WHERE (BookId = ? AND CustId = ?)

名前付きパラメータを使用すると、同じステートメントが次の様に成る。 UPDATE ShoppingCart

SET (BookId = @bookid, CustId = @custid, Quantity = @quantity) WHERE (BookId = @bookid AND CustId = @custid)

(11)

は、プロシージャ自体に依って決定される。パラメータは、SQL ステートメント内のプレースホルダと 厳密に対応しない場合も有る。 ストアドプロシージャでは、名前付きパラメータも使用出来る。其の場合、コレクション内のパラメー タの位置は重要では無い。其の代わり、コレクション内の各パラメータ項目にはParameterName プロ パティが有り、其れを使用してストアドプロシージャ内の対応するパラメータと一致させる。 パラメータコレクションを手動で設定する場合は、ストアドプロシージャで何のパラメータが必要なの かを正確に理解して居る必要が有る。多くのストアドプロシージャは値を返す。其の場合、値はパラメ ータコレクション内でアプリケーションに返される為、其れを可能に仕て置く必要が有る。更に、スト アドプロシージャには、複数の SQL ステートメントが含まれる場合が有り、パラメータコレクション が、プロシージャ内の総てのステートメントに渡される総ての値を反映する必要が有る。 ストアドプロシージャでパラメータに名前が付いて居ない場合、コレクション内の項目はコマンドで必 要なパラメータと位置的に対応する。コマンドがストアドプロシージャで有り、値を返す場合、コレク ション内の最初の項目(項目0)は、此の戻り値の為に確保される。 従って、夫々れのパラメータオブジェクトは、コレクション内のインデックス位置に依って参照出来る。 但し、パラメータオブジェクトは、パラメータを其の順序と関係無く参照する為のParameterName プ ロパティもサポートして居る。例えば、コレクションの2 番目のパラメータが Title_Keyword と謂う名 前で有る場合、次の2 つのステートメントは等しく成る。 Visual Basic ' ワイルドカードで囲んだキーワード

titleKeyword = "%" & txtTitleKeyword.Text & "%"

OleDbDataAdapter1.SelectCommand.Parameters(1).Value = titleKeyword

OleDbDataAdapter1.SelectCommand.Parameters("Title_Keyword").Value = titleKeyword C#

// ワイルドカードで囲んだキーワード

string titleKeyword = "%" + txtTitleKeyword.Text + "%";

this.OleDbDataAdapter1.SelectCommand.Parameters[1].Value = titleKeyword; this.OleDbDataAdapter1.SelectCommand.Parameters["Title_Keyword"].Value = titleKeyword; 一般に、インデックス値でパラメータを参照するよりも、パラメータ名を使用する方がプログラミング 手法と仕ては優れて居る。何故なら、パラメータの数が変更された時の必要な保守作業が減り、亦、ス トアドプロシージャが値を返すか何うかを覚えて置く必要が無いからで有る。パラメータを名前で参照 する場合は、インデックス値で参照する場合よりも、僅かにオーバーヘッドが増えるが、此れはプログ ラミングの簡単さとアプリケーションの保守性に依って相殺される。 パラメータ値の確立 パラメータの値を確立するには、次の2 つの方法が有る。 ・パラメータのValue プロパティを明示的に設定する。 ・パラメータをデータセットテーブルの列に割り当て、必要な時にデータ行から値を抽出する事が出来 る様にする。 データセットに値を格納する場合やコマンドを呼び出す場合(詰まり、選択パラメータの場合)、パラ メータの値を明示的に設定する。例えば、前に示した本を検索する例に於いて、ユーザーがタイトルキ ーワードを入力する為のテキストボックスを、アプリケーションに追加する事も出来る。其の場合、パ

(12)

ラメータの値をテキストボックスのテキストに明示的に設定してから、アダプタのFill メソッドを呼び 出す。此れを行うコードは次の様に成る。此のコードは、テキストボックスの内容をパラメータと仕て 確立してから、データセットに値を格納する。

Visual Basic ' ワイルドカードで囲んだキーワード

titleKeyword = "%" & txtTitleKeyword.Text & "%"

OleDbDataAdapter1.SelectCommand.Parameters("Title_Keyword").Value = titleKeyword OleDbDataAdapter1.Fill(dsAuthors1) C# // ワイルドカードで囲んだキーワード titleKeyword = "%" + txtTitleKeyword.Text + "%"; this.OleDbDataAdapter1.SelectCommand.Parameters["Title_Keyword"].Value = titleKeyword; this.OleDbDataAdapter1.Fill(dsAuthors1); 割り当てられたパラメータ値は、更新時に使用される。アダプタのUpdate メソッドを呼び出すと、メ ソッドは、データセットテーブル内の各レコードに対して個別に適切な更新(更新、挿入、削除)を行 う。其の場合、パラメータの値は、データセットレコード内の列と仕て既に存在して居る。例えば、更 新プロセスがデータベーステーブル内の新しいレコード(データベースで INSERT ステートメントを 呼び出す必要の有るレコード)に達した場合、INSERT ステートメントの VALUE 句に対する値をレコ ードから直接読み取る事が出来る。 此等は、一般的なシナリオだが、其れが総てでは無い。ストアドプロシージャは、out パラメータを使 用して、又は、プロシージャの戻り値を使用してデータを返す場合が有る。其の様な場合、返された値 をデータセットテーブルの列に割り当てる必要が有る。 更新パラメータも明示的に設定する事が可能で有る。アダプタは、行が更新される度に呼び出される RowUpdating イベントをサポートして居る。此のイベントのハンドラを作成して、其の中でパラメー タ値を設定出来る。其れに依り、パラメータ値を精密に制御出来、パラメータ値の作成な何のプロセス をデータベースレコードに書き込む前に動的に実行出来る。

(13)

■ コマンドの使用 ■ ■ 此のセクションの内容 ・コマンドの実行(13 頁) ADO.NET の Command オブジェクトと、其れを使用してデータソースに対してクエリやコマンドを 実行する方法に付いて説明する。 ・コマンドに依るストアドプロシージャの使用(14 頁) Command オブジェクトを使用してストアドプロシージャを呼び出す方法に付いて説明する。パラメ ータ値の受け渡しに付いての情報も含まれる。 ・コマンドの自動生成(20 頁)

CommandBuilder を使用して、単一テーブルを対象とする SELECT コマンドを持つ DataAdapter に対応してINSERT、UPDATE、DELETE の各コマンドを自動的に生成する方法に付いて説明する。 ・データベースからの単一の値の取得(23 頁) Command オブジェクトを使用してデータベースクエリから単一の値を返す方法に付いて説明する。 ■ コマンドの実行 Command オブジェクトは、目的のアクションを実行する為に使用出来る様々な Execute メソッドを公 開する。結果をデータストリームと仕て返す時は、ExecuteReader を使用して DataReader オブジェク トを返す。シングルトン値を返すには、ExecuteScalar を使用する。行を返さないコマンドを実行する にはExecuteNonQuery を使用する。 ストアドプロシージャと共に Command オブジェクトを使用する時は、Command オブジェクトの CommandType プ ロ パ テ ィ を StoredProcedure に 設 定 す る 事 も 出 来 る 。 StoredProcedure の CommandType と共に、Command の Parameters プロパティを使用して入力パラメータ、出力パラメ ータ、及び、戻り値にアクセス出来る。Parameters プロパティには、Execute メソッドが呼び出され たか何うかに関係無くアクセス出来る。併し、ExecuteReader を呼び出す時は、DataReader が終了す る迄は、戻り値や出力パラメータにアクセス出来ない。 次のコード例では、SQL Server の Northwind サンプルデータベースから、カテゴリのリストを返す様 にSqlCommand オブジェクトを作成する方法を示す。 Visual Basic Dim command As SqlCommand = New SqlCommand( _

"SELECT CategoryID, CategoryName FROM dbo.Categories", nwindConn) C#

SqlCommand command = new SqlCommand(

"SELECT CategoryID, CategoryName FROM dbo.Categories", nwindConn); ※ 上記で、変数 nwindConn は、有効な SqlConnection オブジェクトとする。 コマンドのパフォーマンスカウンタ

.NET Framework Data Provider for SQL Server には、失敗したコマンド実行に関連して断続的に発 生する問題を検出出来るパフォーマンスカウンタが追加されて居る。パフォーマンスモニタの中 で、.NET CLR Data パフォーマンスオブジェクト内に有る、SqlClient: Total # failed commands (SqlClient:失敗したコマンドの合計数)カウンタにアクセスすると、何等かの理由で失敗したコマン ド実行の合計数を確認出来る。

(14)

※ .NET Framework Data Provider for SQL Server のパフォーマンスカウンタを ASP.NET アプリケ ーションと共に使用する場合は、_Global インスタンス而巳使用する事を推奨する。従って、パフォ ーマンスカウンタが返す値は、総てのASP.NET アプリケーションのカウンタ値の合計と成る。 ■ コマンドに依るストアドプロシージャの使用 ストアドプロシージャは、データドリブンのアプリケーションに多くの利点を提供する。ストアドプロ シージャを使用すると、データベースの操作を単一のコマンドにカプセル化し、最大のパフォーマンス が得られる様に最適化し、更に追加のセキュリティ機能を使用して、セキュリティを強化する事が出来 る。ストアドプロシージャは、ストアドプロシージャ名の後にパラメータ引数を記述して SQL ステー ト メ ン ト と 仕 て 渡 す 丈 で 呼 び 出 す 事 が 出 来 る が 、ADO.NET の DbCommand オブジェクトの Parameters コレクションを使用すると、ストアドプロシージャをより明示的に定義出来、出力パラメ ータや戻り値にもアクセス出来る。

ストアドプロシージャを呼び出すには、Command オブジェクトの CommandType を StoredProcedure に設定する。次の例に示す様に、CommandType を StoredProcedure に設定した後、Parameters コレ クションを使用してパラメータを定義出来る。

※ OdbcCommand では、ストアドプロシージャを呼び出す時に ODBC CALL 構文全体を入力する必 要が有る。

Visual Basic

' 変数 connection は、有効な SqlConnection オブジェクトとする。

Dim salesCommand As SqlCommand = New SqlCommand( "SalesByCategory", connection ) salesCommand.CommandType = CommandType.StoredProcedure

Dim parameter As SqlParameter = salesCommand.Parameters.Add( _ "@CategoryName", SqlDbType.NVarChar, 15)

parameter.Value = "Beverages" connection.Open( )

Dim reader As SqlDataReader = salesCommand.ExecuteReader( ) Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)) Do While reader.Read( )

Console.WriteLine("{0}, ${1}", reader.GetString(0), reader.GetDecimal(1)) Loop

reader.Close( ) connection.Close( )

C#

// 変数 connection は、有効な SqlConnection オブジェクトとする。

SqlCommand salesCommand = new SqlCommand("SalesByCategory", connection); salesCommand.CommandType = CommandType.StoredProcedure;

SqlParameter parameter = salesCommand.Parameters.Add( "@CategoryName", SqlDbType.NVarChar, 15);

(15)

connection.Open( );

SqlDataReader reader = salesCommand.ExecuteReader( );

Console.WriteLine( "{0}, {1}", reader.GetName(0), reader.GetName(1)); while (reader.Read( ))

{

Console.WriteLine("{0}, ${1}", reader.GetString(0), reader.GetDecimal(1)); }

reader.Close( ); connection.Close( );

Parameter オブジェクトを作成するには、Parameter コンストラクタを使用するか、又は、Command のParameters コレクションの Add メソッドを呼び出す。Parameters.Add は、入力と仕てコンストラ クタ引数、又は、既存のParameter オブジェクトを受け取る。Parameter の Value を null 参照に設定 する時は、DBNull.Value を使用する。 Input パラメータ以外のパラメータに対して ParameterDirection プロパティを設定し、パラメータタ イプがInputOutput、Output、ReturnValue の内の孰れで有るかを指定する必要が有る。様々なプロ バイダに付いて、Input、Output、ReturnValue の各パラメータの作成に関する違いを次の例に示す。 SqlClient の例 Visual Basic ' 変数 connection は、有効な SqlConnection オブジェクトとする。

Dim command As SqlCommand = New SqlCommand("SampleProc", connection) command.CommandType = CommandType.StoredProcedure

Dim parameter As SqlParameter = command.Parameters.Add( _ "RETURN_VALUE", SqlDbType.Int)

parameter.Direction = ParameterDirection.ReturnValue

parameter = command.Parameters.Add( "@InputParm", SqlDbType.NVarChar, 12) parameter.Value = "Sample Value"

parameter = command.Parameters.Add( "@OutputParm", SqlDbType.NVarChar, 28) parameter.Direction = ParameterDirection.Output

connection.Open( )

Dim reader As SqlDataReader = command.ExecuteReader( )

Console.WriteLine( "{0}, {1}", reader.GetName(0), reader.GetName(1)) Do While reader.Read( )

Console.WriteLine( "{0}, {1}", reader.GetInt32(0), reader.GetString(1)) Loop

reader.Close( ) connection.Close( )

(16)

Console.WriteLine( " @OutputParm: {0}", command.Parameters("@OutputParm").Value)

Console.WriteLine( "RETURN_VALUE: {0}", command.Parameters("RETURN_VALUE").Value) C#

// 変数 connection は、有効な SqlConnection オブジェクトとする。 SqlCommand command = new SqlCommand("SampleProc", connection); command.CommandType = CommandType.StoredProcedure;

SqlParameter parameter = command.Parameters.Add("RETURN_VALUE", SqlDbType.Int); parameter.Direction = ParameterDirection.ReturnValue;

parameter = command.Parameters.Add("@InputParm", SqlDbType.NVarChar, 12); parameter.Value = "Sample Value";

parameter = command.Parameters.Add("@OutputParm", SqlDbType.NVarChar, 28); parameter.Direction = ParameterDirection.Output;

connection.Open( );

SqlDataReader reader = command.ExecuteReader( );

Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)); while (reader.Read( ))

{

Console.WriteLine("{0}, {1}", reader.GetInt32(0), reader.GetString(1)); }

reader.Close( ); connection.Close( );

Console.WriteLine(" @OutputParm: {0}", command.Parameters["@OutputParm"].Value);

Console.WriteLine("RETURN_VALUE: {0}", command.Parameters["RETURN_VALUE"].Value); OleDb の例

Visual Basic

' 変数 connection は、有効な OleDbConnection オブジェクトとする。

Dim command As OleDbCommand = New OleDbCommand( "SampleProc", connection) command.CommandType = CommandType.StoredProcedure

Dim parameter As OleDbParameter = command.Parameters.Add( _ "RETURN_VALUE", OleDbType.Integer)

parameter.Direction = ParameterDirection.ReturnValue

parameter = command.Parameters.Add( "@InputParm", OleDbType.VarChar, 12) parameter.Value = "Sample Value"

parameter = command.Parameters.Add( "@OutputParm", OleDbType.VarChar, 28) parameter.Direction = ParameterDirection.Output

connection.Open( )

(17)

Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)) Do While reader.Read( )

Console.WriteLine("{0}, {1}", reader.GetInt32(0), reader.GetString(1)) Loop

reader.Close( ) connection.Close( )

Console.WriteLine(" @OutputParm: {0}", command.Parameters("@OutputParm").Value)

Console.WriteLine("RETURN_VALUE: {0}", command.Parameters("RETURN_VALUE").Value) C#

// 変数 connection は、有効な OleDbConnection オブジェクトとする。

OleDbCommand command = new OleDbCommand("SampleProc", connection); command.CommandType = CommandType.StoredProcedure;

OleDbParameter parameter = command.Parameters.Add( "RETURN_VALUE", OleDbType.Integer);

parameter.Direction = ParameterDirection.ReturnValue;

parameter = command.Parameters.Add("@InputParm", OleDbType.VarChar, 12); parameter.Value = "Sample Value";

parameter = command.Parameters.Add("@OutputParm", OleDbType.VarChar, 28); parameter.Direction = ParameterDirection.Output;

connection.Open( );

OleDbDataReader reader = command.ExecuteReader( );

Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)); while (reader.Read( ))

{

Console.WriteLine("{0}, {1}", reader.GetInt32(0), reader.GetString(1)); }

reader.Close( ); connection.Close( );

Console.WriteLine(" @OutputParm: {0}", command.Parameters["@OutputParm"].Value);

Console.WriteLine("RETURN_VALUE: {0}", command.Parameters["RETURN_VALUE"].Value); Odbc の例

Visual Basic

' 変数 connection は、有効な OdbcConnection オブジェクトとする。 Dim command As OdbcCommand = New OdbcCommand( _

"{ ? = CALL SampleProc(?, ?) }", connection)

command.CommandType = CommandType.StoredProcedure Dim parameter As OdbcParameter = command.Parameters.Add( _ "RETURN_VALUE", OdbcType.Int)

(18)

parameter = command.Parameters.Add( "@InputParm", OdbcType.VarChar, 12) parameter.Value = "Sample Value"

parameter = command.Parameters.Add( "@OutputParm", OdbcType.VarChar, 28) parameter.Direction = ParameterDirection.Output

connection.Open( )

Dim reader As OdbcDataReader = command.ExecuteReader( ) Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)) Do While reader.Read( )

Console.WriteLine("{0}, {1}", reader.GetInt32(0), reader.GetString(1)) Loop

reader.Close( ) connection.Close( )

Console.WriteLine(" @OutputParm: {0}", command.Parameters("@OutputParm").Value)

Console.WriteLine("RETURN_VALUE: {0}", command.Parameters("RETURN_VALUE").Value) C#

// 変数 connection は、有効な OdbcConnection オブジェクトとする。 OdbcCommand command = new OdbcCommand( _

"{ ? = CALL SampleProc(?, ?) }", connection);

command.CommandType = CommandType.StoredProcedure; OdbcParameter parameter = command.Parameters.Add( _ "RETURN_VALUE", OdbcType.Int);

parameter.Direction = ParameterDirection.ReturnValue;

parameter = command.Parameters.Add( "@InputParm", OdbcType.VarChar, 12); parameter.Value = "Sample Value";

parameter = command.Parameters.Add( "@OutputParm", OdbcType.VarChar, 28); parameter.Direction = ParameterDirection.Output;

connection.Open( );

OdbcDataReader reader = command.ExecuteReader( );

Console.WriteLine("{0}, {1}", reader.GetName(0), reader.GetName(1)); while (reader.Read( )) { Console.WriteLine( _ "{0}, {1}", reader.GetInt32(0), reader.GetString(1)); } reader.Close( ); connection.Close( );

Console.WriteLine(" @OutputParm: {0}", command.Parameters["@OutputParm"].Value);

(19)

SqlCommand に依るパラメータの使用

SqlCommand でパラメータを使用する時は、Parameters コレクションに追加したパラメータの名前が、 ストアドプロシージャ内のパラメータマーカーの名前と一致して居る必要が有る。.NET Framework Data Provider for SQL Server は、ストアドプロシージャ内のパラメータを名前付きのパラメータと看 做して、一致するパラメータマーカーを検索する。

.NET Framework Data Provider for SQL Server は、SQL ステートメントやストアドプロシージャに パラメータを渡す場合の疑問符( ? )プレースホルダをサポートして居ない。此の場合は、次の例に 示す様に名前付きのパラメータを使用する必要が有る。此の例では、@CustomerID が名前付きのパラ メータで有る。

SELECT * FROM Customers WHERE CustomerID = @CustomerID OleDbCommand 又は OdbcCommand に依るパラメータの使用

OleDbCommand 又は OdbcCommand でパラメータを使用する時は、Parameters コレクションにパラ メータが追加されて居る順序が、ストアドプロシージャ内でパラメータが定義されて居る順序と一致し て居る必要が有る。.NET Framework Data Provider for OLE DB と.NET Framework Data Provider for ODBC は、ストアドプロシージャ内のパラメータをプレースホルダと仕て処理し、順にパラメータ 値を適用する。亦、戻り値パラメータは、Parameters コレクションに最初に追加されたパラメータに する必要が有る。

OLE DB の.NET データプロバイダと ODBC の.NET データプロバイダは、SQL ステートメントやス トアドプロシージャにパラメータを渡す場合の名前付きのパラメータをサポートして居ない。此の場合 は、次の例に示す様に疑問符( ? )プレースホルダを使用する必要が有る。

SELECT * FROM Customers WHERE CustomerID = ?

従って、Parameters コレクションに Parameter オブジェクトを追加する順序は、パラメータの疑問符 ( ? )プレースホルダの位置と完全に対応して居る必要が有る。 パラメータ情報の派生 CommandBuilder クラスを使用してストアドプロシージャからパラメータを派生させる事が出来る。 SqlCommandBuilder ク ラ ス と OleDbCommandBuilder ク ラ ス は 、 孰 れ も 静 的 メ ソ ッ ド DeriveParameters を提供する。此のメソッドは、ストアドプロシージャから得られたパラメータ情報 を使用して、Command オブジェクトの Parameters コレクションを設定する。DeriveParameters は Command の既存のパラメータ情報を上書きする。

パラメータ情報の派生には、情報のデータソースへの追加のトリップが必要で有る。パラメータ情報が デザイン時に解って居る場合は、パラメータを明示的に設定する事でアプリケーションのパフォーマン スを改善出来る。

CommandBuilder.DeriveParameters を使用して Command オブジェクトの Parameters コレクショ ンを設定する方法を次のコード例に示す。

Visual Basic

' 変数 connection は、有効な SqlConnection オブジェクトとする。

Dim salesCommand As SqlCommand = New SqlCommand( "Sales By Year", connection) salesCommand.CommandType = CommandType.StoredProcedure

(20)

connection.Open( )

SqlCommandBuilder.DeriveParameters(salesCommand) connection.Close( )

C#

// 変数 connection は、有効な SqlConnection オブジェクトとする。

SqlCommand salesCommand = new SqlCommand("Sales By Year", connection); salesCommand.CommandType = CommandType.StoredProcedure; connection.Open( ); SqlCommandBuilder.DeriveParameters(salesCommand); connection.Close( ); ■ コマンドの自動生成 SelectCommand プロパティが実行時に動的に指定される場合、例えばクエリツールを使用してユーザ ーの記述したクエリ構文を解釈する場合は、適切な InsertCommand、UpdateCommand、又は DeleteCommand をデザイン時に指定する事は出来ない。DataTable を単一データベーステーブルに割 り当てたり、単一データベースから生成する場合は、DbCommandBuilder オブジェクトを利用して自 動的にDbDataAdapter の DeleteCommand、InsertCommand、UpdateCommand を生成出来る。 コマンドを自動的に生成する為の最低限の条件と仕て、SelectCommand プロパティを設定する必要が 有る。SelectCommand プロパティで取得したテーブルスキーマに依って、自動的に生成される INSERT、 UPDATE、DELETE の各ステートメントの構文が決定される。

DbCommandBuilder は、INSERT、UPDATE、DELETE の各コマンドを生成する為に SelectCommand を実行する必要が有る。其の結果、データソースへの追加のトリップが必要に成る為、パフォーマンス が低下する可能性が有る。最適のパフォーマンスを実現するには、明示的にコマンドを指定し、 DbCommandBuilder を使用しない様にする。

SelectCommand は、少なく共 1 つの主キー、又は、一意の列を返す必要が有る。孰れも存在しない場 合は、InvalidOperation 例外が生成され、コマンドは生成されない。

DataAdapter との関連付けが行われて居て、DataAdapter の InsertCommand、UpdateCommand、 DeleteCommand の各プロパティが null 参照で有る場合、DbCommandBuilder は自動的に此等のプロ パティを生成する。プロパティに対して既に Command が存在する場合は、既存の Command が使用 される。 複数のテーブルを結合して作成したデータベースビューは、単一データベーステーブルとは看做されな い。此の場合は、DbCommandBuilder を使用してコマンドを自動的に生成出来ない為、コマンドを明 示的に指定する必要が有る。DataSet に対する更新を元のデータソースに反映させるコマンドを明示的 に設定する方法に付いては、「DataAdapter に依るデータソースの更新」を参照され度い。 出力パラメータをDataSet の更新行に割り当てる事が必要な場合が有る。一般的なタスクの 1 つは、デ ータソースの自動的に生成された ID フィールド、又は、タイムスタンプの値を取得する事で有る。 DbCommandBuilder は、既定では更新行の列に出力パラメータを割り当てない。其の場合は、コマン ドを明示的に指定する必要が有る。自動的に生成された ID フィールドを挿入行の列に割り当てる例に 付いては、「ID 値、及び、Autonumber 値の取得」を参照され度い。 コマンドの自動生成規則 コマンドの自動生成規則を次の表に示す。

(21)

コマンド 規則

InsertCommand RowState が Added に設定されて居るテーブル内の総ての行に対して、データソースの行を挿 入する。更新可能な総ての列に対して値を挿入する(但し、ID、式、タイムスタンプ等の列は 除く)。

UpdateCommand RowState が Modified に設定されて居るテーブルの総ての行に該当するデータソース側の行 を更新する。ID や式等の更新不可能な列を除く、総ての列の値を更新する。データソースの 列の値と該当行の主キー列の値が一致し、更にデータソースの其他の列が其の行の元の値と一 致する総ての行を更新する。詳細に付いては、此の資料で後述する「更新と削除のオプティミ スティック同時実行制御」を参照され度い。

DeleteCommand RowState が Deleted に設定されて居るテーブルの総ての行に該当するデータソース側の行を 削除する。列の値と其の行の主キー列の値が一致し、更にデータソースの其他の列が其の行の 元の値と一致する総ての行を削除する。詳細に付いては、此の資料で後述する「更新と削除の オプティミスティック同時実行制御」を参照され度い。 更新及び削除のオプティミスティック同時実行制御 UPDATE ステートメントや DELETE ステートメントに対するコマンドの自動生成ロジックは、オプテ ィミスティック同時実行制御に基づいて居る。此れは、詰まり、編集時にレコードがロックされず、他 のユーザーやプロセスが其のレコードを何時でも変更出来る事を意味する。レコードは SELECT ステ ートメントに依って返された後、UPDATE ステートメントや DELETE ステートメントの実行前に変更 されて居る可能性も有る為、自動的に生成されるUPDATE ステートメントや DELETE ステートメン トには、元の総ての値を含み、データソースから削除されて居ない行丈を更新する様に指定した WHERE 句が含まれる。此れに依り、新しいデータが上書きされるのを防ぐ。自動的に生成された更新 コマンドが削除済み、又は、DataSet に有る元の値が含まれて居ない行を更新し様とすると、コマンド は何のレコードにも反映されずに、DBConcurrencyException がスローされる。

元 の 値 と は 関 係 無 く UPDATE や DELETE を 実 行 す る 場 合 は 、 DataAdapter に 明 示 的 に UpdateCommand を設定し、コマンドの自動生成は行わない。 コマンドの自動生成ロジックの制限事項 コマンドの自動生成には、次の制限事項が適用される。 ・リレーションシップの無いテーブルに限定 コマンドの自動生成ロジックでは、データソースの他のテーブルへのリレーションシップを考慮せず に、独立したテーブルを対象と仕てINSERT、UPDATE、DELETE の各ステートメントを生成する。 其の結果、Update を呼び出してデータベースの外部キー制約に関係する列に対する変更を発行する と、エラーが発生する場合が有る。此の様な例外を防ぐには、外部キー制約に関係する列の更新には DbCommandBuilder を使用せず、更新操作を実行するステートメントを明示的に指定する。 ・テーブル名と列名 列名やテーブル名にスペース、ピリオド( . )、疑問符( ? )、引用符、其他の英数字以外の特殊文 字が含まれて居ると、仮令、其等の文字が角括弧で囲まれて居ても、コマンドの自動生成ロジックは エラーに成る。catalog.schema.table の形式を採るテーブルの完全修飾名はサポートされて居る。 CommandBuilder に依る SQL ステートメントの自動生成 DataAdapter に対して SQL ステートメントを自動的に生成するには、先ず、DataAdapter の SelectCommand プ ロ パ テ ィ を 設 定 す る 。 次 に 、 CommandBuilder オ ブ ジ ェ ク ト を 作 成 し 、 CommandBuilder で SQL ステートメントを自動的に生成する DataAdapter を引数と仕て指定する。

(22)

Visual Basic

' 変数 connection は、有効な SqlConnection オブジェクトとする。 Dim adapter As SqlDataAdapter = New SqlDataAdapter( _ "SELECT * FROM dbo.Customers", connection)

Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter) builder.QuotePrefix = "["

builder.QuoteSuffix = "]"

Dim custDS As DataSet = New DataSet connection.Open( ) adapter.Fill(custDS, "Customers") ' 此処でデータセット内のデータを検証するコードを記述 ' SqlCommandBuilder が無ければ、此の行は失敗する。 adapter.Update(custDS, "Customers") connection.Close( ) C# // 変数 connection は、有効な SqlConnection オブジェクトとする。 SqlDataAdapter adapter = new SqlDataAdapter(

"SELECT * FROM dbo.Customers", connection);

SqlCommandBuilder builder = new SqlCommandBuilder(adapter); builder.QuotePrefix = "[";

builder.QuoteSuffix = "]";

DataSet custDS = new DataSet( ); connection.Open( ); adapter.Fill(custDS, "Customers"); // 此処でデータセット内のデータを検証するコードを記述 // SqlCommandBuilder が無ければ、此の行は失敗する。 adapter.Update(custDS, "Customers"); connection.Close( ); SelectCommand の変更

INSERT、UPDATE、DELETE の各コマンドを自動生成した後に SelectCommand の CommandText を変更すると、例外が発生する事が有る。変更された SelectCommand.CommandText に、INSERT、 UPDATE、DELETE の各コマンドの自動生成時に使用した SelectCommand.CommandText と矛盾す るスキーマ情報が含まれて居る場合、後続のDataAdapter.Update メソッド呼び出しでアクセスする列 はSelectCommand に依って参照された現在のテーブルには存在しない可能性が有り、例外が発生する。 CommandBuilder の RefreshSchema メソッドを呼び出す事で、自動的にコマンドを生成する CommandBuilder が使用するスキーマ情報を更新出来る。 何 の コ マ ン ド が 自 動 的 に 生 成 さ れ た か を 確 認 す る に は 、CommandBuilder オ ブ ジ ェ ク ト の GetInsertCommand、GetUpdateCommand、GetDeleteCommand の各メソッドを使用して、自動的 に生成されたコマンドへの参照を取得し、関連付けられて居る Command の CommandText プロパテ ィを確認する。

(23)

自動的に生成された更新コマンドをコンソールに出力するコード例を次に示す。 Console.WriteLine(builder.GetUpdateCommand( ).CommandText) 次に示す例は、前述の例の続きのコードで有る。此の例では、CompanyName 列を ContactName 列に 置き換えてCustomers テーブルを再作成する。RefreshSchema メソッドを呼び出し、新しい列情報を 使用して、自動的に生成されたコマンドを更新する。 Visual Basic ' 変数 connection は、有効な SqlConnection オブジェクトとする。 connection.Open( ) adapter.SelectCommand.CommandText = _

"SELECT CustomerID, ContactName FROM dbo.Customers" builder.RefreshSchema( ) custDS.Tables.Remove(custDS.Tables("Customers")) adapter.Fill(custDS, "Customers") ' 此処でデータセット内のデータを検証するコードを記述 ' SqlCommandBuilder が無ければ、此の行は失敗する。 adapter.Update(custDS, "Customers") connection.Close( ) C# // 変数 connection は、有効な SqlConnection オブジェクトとする。 connection.Open( ); adapter.SelectCommand.CommandText =

"SELECT CustomerID, ContactName FROM dbo.Customers"; builder.RefreshSchema( ); custDS.Tables.Remove(custDS.Tables["Customers"]); adapter.Fill(custDS, "Customers"); // 此処でデータセット内のデータを検証するコードを記述 // SqlCommandBuilder が無ければ、此の行は失敗する。 adapter.Update(custDS, "Customers"); connection.Close( ); ■ データベースからの単一の値の取得 テーブルやデータストリームの形式ではなく、単に1 つの値をデータベース情報と仕て返す事が必要な 場合が有る。例えば、COUNT(*)、SUM(Price)、AVG(Quantity) 等の集約関数の結果を返す場合で有 る。Command オブジェクトは、ExecuteScalar メソッドを使用して単一の値を返す機能を提供する。 ExecuteScalar メソッドは、結果セットの 1 行目の 1 列目の値をスカラ値と仕て返す。 SqlCommand の ExecuteScalar メソッドを使用してテーブル内のレコード数を返すコード例を次に示

(24)

す。SELECT ステートメントは、Transact-SQL COUNT 集約関数を使用して、指定されたテーブルの 行数を表す1 つの値を返す。

Visual Basic

' 変数 connection は、有効な SqlConnection オブジェクトとする。 Dim ordersCMD As SqlCommand = New SqlCommand( _

"SELECT COUNT(*) FROM dbo.Orders", connection) Dim count As Int32 = CInt(ordersCMD.ExecuteScalar( ))

C#

// 変数 connection は、有効な SqlConnection オブジェクトとする。 SqlCommand ordersCMD = new SqlCommand(

"SELECT Count(*) FROM Orders", connection); Int32 count = (Int32)ordersCMD.ExecuteScalar( );

参照

関連したドキュメント

'BOM for Windows Ver.8.0 インストールマニュアル'では、BOM for Windows

Bluetooth® Low Energy プロトコルスタック GUI ツールは、Microsoft Visual Studio 2012 でビルドされた C++アプリケーションです。GUI

Visual Studio 2008、または Visual Studio 2010 で開発した要素モデルを Visual Studio

前項においては、最高裁平成17年6月9日決定の概要と意義を述べてき

データベースには,1900 年以降に発生した 2 万 2 千件以上の世界中の大規模災 害の情報がある

本文書の目的は、 Allbirds の製品におけるカーボンフットプリントの計算方法、前提条件、デー タソース、および今後の改善点の概要を提供し、より詳細な情報を共有することです。

操作は前章と同じです。但し中継子機の ACSH は、親機では無く中継器が送信する電波を受信します。本機を 前章①の操作で

すべての Web ページで HTTPS でのアクセスを提供することが必要である。サーバー証 明書を使った HTTPS