データベース内のデータを表示、編集、挿入または削除するには、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
表に含まれていないことを確認します。
アプリケーションを閉じます。