データベース内のデータを表示、編集、挿入または削除するには、SQLコマンド、ストアド・プロシージャまたは表名を指定して、OracleCommandオブジェクトにリクエストをカプセル化する必要があります。OracleCommandオブジェクトは、リクエストを作成してデータベースに送信し、結果を戻します。
コマンド・オブジェクトを使用するには、次の手順を実行します。
第3章「ODP.NETによる単純な.NETアプリケーションの作成」で作成したアプリケーションHR_Connect_xxから、Form1.xxのコピーを2つ作成します。 コピーを作成する方法については、付録B「フォームのコピー」を参照してください。
コピーにForm2.csまたはForm2.vb、およびForm3.csまたはForm3.vbと名前を付けます。最初のコピーは、この章の前半で使用します。2つ目のコピーは、この章の後半で使用します。
Form2.csまたはForm2.vbを開きます。
コード・ファイルの名前は変更しましたが、プロジェクト内の実際のフォーム・コントロールの名前は変更していないため、デザイナのフォームはまだForm1となっていることに注意してください。
SQL問合せを表す文字列を作成し、try文の本体に追加します。
新しいコードは太字で示しています。
Visual C#:
try
{
conn.Open();
connect.Enabled = false;
// SQL Statement
string sql = "select department_name from departments"
+ " where department_id = 10";
}
Visual Basic:
Try
conn.Open()
connect.Enabled = False
Dim sql As String = "select department_name from departments" & _
"where department_id = 10"
新しいsql変数を使用してOracleCommandオブジェクトを作成し、テキスト・コマンドが実行されるようにCommandTypeプロパティを設定します。
Visual C#:
try
{
conn.Open();
connect.Enabled = false;
// SQL Statement
string sql = "select department_name from departments"
+ " where department_id = 10";
OracleCommand cmd = new OracleCommand(sql, conn);
cmd.CommandType = CommandType.Text;
}
Visual Basic:
Try
conn.Open()
connect.Enabled = False
Dim sql As String = "select department_name from departments" & _
"where department_id = 10"
Dim cmd As New OracleCommand(sql, conn)
cmd.CommandType = CommandType.Text
実行した内容を保存します。
この項では、データベースからデータを取得する方法を説明します。
OracleCommandオブジェクトのExecuteReader()メソッドによりOracleDataReaderオブジェクトが戻されます。これにアクセスすることでフォームに結果を表示できます。このアプリケーションでは、ListBoxを使用して結果を表示します。
データを取得するには、次の手順を実行します。
次に示すコードをconnect_Click()メソッドのTryブロックの最後に追加して、OracleDataReaderオブジェクトを作成します。
これにより、問合せ結果を読み取ることができます。
Visual C#:
OracleDataReader dr = cmd.ExecuteReader(); dr.Read();
Visual Basic:
Dim dr As OracleDataReader = cmd.ExecuteReader() dr.Read()
設計ビューでForm1を開きます。「View」メニューから「Designer」を選択します。
「View」メニューから「Toolbox」を選択します。
「Toolbox」から「Label」を選択し、Form1にドラッグします。
「View」メニューから「Properties Window」を選択します。
「Properties」ウィンドウで、ラベルの「Text」をDepartmentに変更します。
「Toolbox」の「Window」フォームから、「ListBox」を選択し、Form1にドラッグします。
「Properties」ウィンドウの「Design」で、「Name」をdepartmentsに変更します。

問合せ結果からデータを取得するためのアクセッサ型メソッドを追加します。
「Connect」ボタンをダブルクリックしてconnect_click()メソッドを編集し、次に示すコードをTryブロックの最後に追加します。
Visual C#:
departments.Items.Add(dr.GetString(0));
Visual Basic:
departments.Items.Add(dr.GetString(0))
GetStringなどの型指定されたアクセッサは、ネイティブの.NETデータ型およびネイティブのOracleデータ型を戻します。結果セットのどの列を戻すかは、アクセッサに渡されたゼロベースの序数で指定します。
アプリケーションをビルドして保存します。
アプリケーションを実行します。ログインおよびデータソースを入力します。
接続すると、「Department」リスト・ボックスにAdministrationと表示されます。これはHRスキーマに含まれる部門番号10の正しい名前で、SELECT文でリクエストしたものです。

バインド変数はSQL文内のプレースホルダです。データベースではSQL文を受信すると、その文がすでに実行されたことがありメモリーに格納されているかどうかが確認されます。その文がメモリーに存在する場合、Oracle Databaseではその文を再利用でき、文の解析と最適化のタスクがスキップされます。バインド変数を使用すると、異なる入力値でも文の再利用が可能です。また、バインド変数を使用すると、データベースの問合せパフォーマンスが向上するだけでなく、入力に含まれるリテラル引用符の特別な処理が不要になり、SQLインジェクション攻撃から保護することができます。
次のコードは、バインド変数を使用せずに、文のWHERE句に値10を指定する標準的なSELECT文です。
SELECT department_name FROM departments WHERE department_id = 10
次のコードは、数値をバインド変数:department_idで置き換えたものです。バインド変数識別子は、常に1つのコロン(:)で始まります。
SELECT department_name FROM departments WHERE department_id = :department_id
バインド変数はUPDATE、INSERTおよびDELETE文でも使用でき、ストアド・プロシージャでも使用できます。次のコードは、UPDATE文でバインド変数を使用する方法を示しています。
UPDATE departments SET department_name = :department_name WHERE departname_id = : department_id
詳細は、「データの挿入、削除および更新」を参照してください。
.NETコードで各バインド変数を表すには、OracleParameterクラスを使用できます。OracleParameterCollectionクラスには、各文のOracleCommandオブジェクトと関連付けられたOracleParameterオブジェクトが含まれています。OracleCommandクラスは、SQL文をデータベースに渡し、結果をアプリケーションに戻します。
変数は、OracleCommandプロパティBindByNameの設定(デフォルトはfalse)によって、位置または名前でバインドできます。
位置指定によるバインド
Add()メソッドを使用して、SQL文またはストアド・プロシージャで記述されるのと同じ順序でパラメータをOracleParameterCollectionに追加する必要があります。
名前指定によるバインド
任意の順序でパラメータをコレクションに追加できます。ただし、パラメータ・オブジェクトのParameterNameプロパティを、ストアド・プロシージャで宣言されているバインド変数識別子と同じ名前に設定する必要があります。
バインド・モード(位置指定または名前指定)の他に、.NET開発者はDirection、OracleDbType、SizeおよびValueの各プロパティを、各パラメータ・オブジェクトに設定します。
Directionバインド変数は、出力、入力または入出力パラメータとして使用できます。Directionプロパティは、各パラメータの向きを示します。Directionプロパティのデフォルト値はInputです。
OracleDbTypeプロパティは、パラメータがnumber、date、VARCHAR2などのいずれであるかを示します。
Sizeは、VARCHAR2などの可変長データ型のパラメータで保持できる最大データ・サイズを示します。
Valueには、文の実行前(入力パラメータ)、実行後(出力パラメータ)または実行前後の両方(入出力パラメータ)のパラメータ値が保持されます。
バインド変数を使用してデータを取得するには、次の手順を実行します。
Departmentsという名前のListBoxを右側に移動します。
「View」メニューから「Toolbox」を選択します。
「Toolbox」から「TextBox」を選択し、Form1のDepartmentという名前のラベルの下にドラッグします。
「View」メニューから「Properties Window」を選択します。
「Properties」ウィンドウで、「Name」をdepartmentIDに変更します。

次に示すコードをconnect_Click()メソッドのTryブロックに追加して、バインド変数が使用されるようにSELECT文を変更します。
変更されたコードまたは新しいコードは太字で示しています。
Visual C#:
string sql = "select department_name from departments where department_id = " + ":department_id"; OracleCommand cmd = new OracleCommand(sql, conn); cmd.CommandType = CommandType.Text; OracleParameter p_department_id = new OracleParameter(); p_department_id.OracleDbType = OracleDbType.Decimal; p_department_id.Value = departmentID.Text; cmd.Parameters.Add(p_department_id); OracleDataReader dr = cmd.ExecuteReader(); dr.Read(); departments.Items.Add(dr.GetString(0));
Visual Basic:
Dim sql As String = "select department_name from departments where" & _ "department_id= ":department_id" Dim cmd As OracleCommand = New OracleCommand(sql, conn) cmd.CommandType = CommandType.Text Dim p_department_id as OracleParameter = new OracleParameter() p_department_id.OracleDbType = OracleDbType.Decimal p_department_id.Value = departmentID.Text cmd.Parameters.Add(p_department_id) Dim dr As OracleDataReader = cmd.ExecuteReader() dr.Read() departments.Items.Add(dr.GetString(0))
このコードでは、パラメータ・オブジェクトはOracleDbTypeプロパティを設定しますが、Directionプロパティにはデフォルト値Inputを使用するため、設定は不要です。オブジェクトは入力パラメータであり、データ・プロバイダは値からサイズを判断できるため、Sizeプロパティを設定する必要はありません。
アプリケーションを保存して実行します。
ログイン情報と、HRスキーマの代表的な部門番号(50など)を入力します。
「Connect」をクリックします。
部門IDに対応する部門名がアプリケーションから戻されます。

データベースから複数の値を取得することが必要になる場合はよくあります。複数の列および複数の行の値を取得するには、DataReaderオブジェクトを使用できます。次の例で、複数の列や複数の行に対する問合せについて考えてみます。
SELECT department_id, department_name, manager_id, location_id FROM departments WHERE department_id < 100
DataReaderオブジェクトから複数の行を処理するには、ループ構造が必要です。また、複数の行を表示できるコントロールが役立ちます。OracleDataReaderオブジェクトは前進専用で読取り専用のカーソルであるため、Windows FormsのDataGridコントロールなどの、更新可能なコントロールまたは後方にスクロールできるコントロールにはバインドできません。ただし、OracleDataReaderオブジェクトはListBoxコントロールと互換性があります。
複数の値を取得するには、次の手順を実行します。
connect_Click()メソッドのTryブロックで、複数の行の結果セットが戻され、部門名を表示するreadメソッドを囲むwhileループを追加するようにSQL問合せを変更します。
Visual C#:
try
{
...
string sql = "select department_name from departments where department_id" +
"< :department_id";
...
while (dr.Read())
{
departments.Items.Add(dr.GetString(0));
}
}
Visual Basic:
Try
...
Dim sql As String = "select department_name from departments " & _
"where department_id < :department_id"
...
While (dr.Read())
departments.Items.Add(dr.GetString(0))
End While
アプリケーションを保存して実行します。
ログイン情報を入力し、部門に50と入力します。
「Connect」をクリックします。
問合せに対応する部門名が、アプリケーションから戻されます。

DataSetクラスでは、メモリーに常駐するデータベース・データのコピーが提供されます。これは、リレーショナル・データまたはXMLデータを格納する1つ以上の表で構成されます。OracleDataReaderオブジェクトとは異なり、DataSetは更新可能で後方にスクロールできます。
Datasetクラスを使用するには、次の手順を実行します。
第3章で作成したForm1のコピーを作成していない場合はForm1をコピーし、付録B「フォームのコピー」で説明するとおり、Form3.vbまたは.csという名前を付けます。Form1.xxがSolution Explorerに表示されない場合は、「Project」メニューから「Show All Files」を選択します。
「View」メニューから「Designer」ビューを選択します。
「View」メニューから「Toolbox」を選択します。
「Toolbox」から「DataGridView」を選択し、Form1にドラッグします。
「View」メニューから「Properties Window」を選択します。
「Properties」ウィンドウで、データ・グリッド・ビューの「Name」をdepartmentsに変更します。

「View」メニューから「Code」を選択します。
次に示すように、コードのconn宣言の直後に、クラス変数への変数宣言を追加します。
Visual C#:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private OracleConnection conn = new OracleConnection();
private OracleCommand cmd;
private OracleDataAdapter da;
private OracleCommandBuilder cb;
private DataSet ds;
...
Visual Basic:
Public Class Form1 Dim conn As New OracleConnection Private cmd As OracleCommand Private da As OracleDataAdapter Private cb As OracleCommandBuilder Private ds As DataSet
connect_Click()メソッドのTryブロックに、次のコードを追加します。
データベースを問い合せるコード
コマンドの問合せ結果をDataSetに埋め込むコード
DataSetをデータ・グリッド(departments)にバインドするコード
Visual C#:
conn.Open(); connect.Enabled = false; string sql = "select * from departments where department_id < 60"; cmd = new OracleCommand(sql, conn); cmd.CommandType = CommandType.Text; da = new OracleDataAdapter(cmd); cb = new OracleCommandBuilder(da); ds = new DataSet(); da.Fill(ds); departments.DataSource = ds.Tables[0];
Visual Basic:
conn.Open() connect.Enabled = False Dim sql As String = "select * from departments where department_id < 60" cmd = New OracleCommand(sql, conn) cmd.CommandType = CommandType.Text da = New OracleDataAdapter(cmd) cb = New OracleCommandBuilder(da) ds = New DataSet() da.Fill(ds) departments.DataSource = ds.Tables(0)
アプリケーションをビルドして保存します。
アプリケーションを実行し、ログインおよびデータソースを入力します。
データベースに正しく接続されると、データ・グリッドに問合せ結果が移入されます。

この時点で、DataSetにはデータベース・データのクライアント・コピーが保持されています。この項では、クライアント・データの変更をデータベースに保存できるようにするボタンを追加します。その後の項では、データの更新、挿入および削除のテスト方法を説明します。
DataSetからデータベースにデータを保存できるようにするには、次の手順を実行します。
「Toolbox」から「Button」をForm1にドラッグ・アンド・ドロップします。
「Properties」ウィンドウで、ボタンの「Name」をsaveに変更します。
TextプロパティをSaveに変更します。
「Properties」ウィンドウの上部で、「Events」(稲妻のアイコン)をクリックします。イベントのリストでクリック・イベントを選択します。2番目の列にイベント名save_Clickを入力します。

「View」メニューから「Code」を選択します。
次に示すように、データを更新するコードをsave_Click()メソッドの本体に追加します。
Visual C#:
da.Update(ds.Tables[0]);
Visual Basic:
da.Update(ds.Tables(0))
「Error List」にエラーが表示される場合があります。これらのエラーは、次の手順でコードを追加する表示されなくなります。
Form()メソッドまたはForm1_Loadメソッドに、次のコードを追加します。
Visual C#:
public Form1()
{
InitializeComponent();
save.Enabled = false;
}
Visual Basic:
Private Sub Form1_Load(ByVal sender As System.Object, & _
ByVal e As System.EventArgs) Handles MyBase.Load
save.Enabled = false
次のように、connect_Click()メソッドのTryブロックに、「Save」ボタンを有効にするコードを追加します。
Visual C#:
conn.Open();
...
departments.DataSource = ds.Tables[0];
save.Enabled = true;
Visual Basic:
conn.Open()
...
departments.DataSource = ds.Tables(0)
save.Enabled = True
conn.Dispose()コールをconnect_Click()メソッドのFinallyブロックから削除します。
注意: この例で前に使用したコードでは、接続を破棄またはクローズするためにこのメソッドが必要でした。しかし、コードを変更したため、問合せ結果が戻された後も接続をオープン状態のままにし、エンド・ユーザーによるデータ変更がデータベースに伝播されるようにする必要があります。一般的なオーバーライド・コールであるcomponents.Dispose()は、すでにForm1の定義に含まれています。
アプリケーションをビルドして保存します。
アプリケーションを実行し、ログインおよびデータソースを入力します。
データベースに正しく接続されると、データ・グリッドに問合せ結果が移入されます。

この項では、新しいアプリケーションを使用してデータベースのデータを直接操作する方法を説明します。
データを挿入、削除および更新するには、次の手順を実行します。
前の項で作成したアプリケーションを実行し、ログインおよびデータソースを入力して、データベースに接続します。
データ・グリッドの一番下にある*プロンプトで、新しいレコードを入力します。
「DEPARTMENT_ID」に5と入力します。
「DEPARTMENT_NAME」にCommunity Outreachと入力します。
「MANAGER_ID」には値を入力せず、そのままにします。
「LOCATION_ID」に1700と入力します。

「Save」をクリックします。
アプリケーションを閉じ、新しいレコードが保存されているかどうかを確認します。
アプリケーションを再度実行し、データベースに接続します。
DEPARTMENT_IDが番号順に表示され、新しい部門がDEPARTMENTS表の先頭にあることを確認します。
部門名をCommunity Volunteersに変更して、「Save」ボタンをクリックします。

手順4を繰り返します。アプリケーションを再度実行し、データベースに接続して、部門名が変更されていることを確認します。
変更したばかりのレコード全体を選択し(一番左の列にあるカーソル・アイコンをクリック)、[Delete]キーを使用してこのレコードを削除します。「Save」ボタンをクリックします。 
dataset11.gifの説明
手順4を繰り返します。アプリケーションを再度実行し、データベースに接続して、新しいレコードがDEPARTMENTS表に含まれていないことを確認します。
アプリケーションを閉じます。