第16章 C#からOracle Databaseに接続する
この章の目的
Section titled “この章の目的”この章では、C#のコンソールアプリから Oracle Database に接続し、SQL文を実行してデータを取得する方法を学習します。
前半のSQL研修では、SQL*Plusを使ってOracle Databaseに接続し、employees 表や departments 表を操作しました。
この章では、同じOracle Databaseに対して、C#プログラムから接続します。
これまでの章で学んできた内容は、この章でつながります。
文字列 → 接続文字列やSQL文を扱う
例外処理 → DB接続エラーやSQLエラーに対応する
クラス → DBから取得した1行分のデータを表す
List<T> → DBから取得した複数行のデータを管理する
null許容型 → DBのNULLをC#で扱うこの章では、まずコンソールアプリを使って、次の流れを確認します。
1. SQL*Plusで接続確認する2. Visual Studioでコンソールアプリを作成する3. Oracle接続用のNuGetパッケージを追加する4. C#からOracle Databaseへ接続する5. SELECT文を実行する6. OracleDataReaderで結果を読み取る7. NULL値に注意しながらデータを扱う8. SQLに条件を渡して検索するWebアプリやデスクトップアプリに入る前に、まずはコンソールアプリでDB接続だけを確認します。
重要
Webアプリやデスクトップアプリに直接DB接続を入れると、エラーが発生したときに原因を切り分けにくくなります。
まずコンソールアプリでDB接続を確認しておくことで、後の章で問題が起きたときに、
DB接続の問題かWebアプリの問題かデスクトップアプリの問題かSQL文の問題かを分けて考えやすくなります。
この章でできるようになること
Section titled “この章でできるようになること”この章を終えると、次のことができるようになります。
- SQL*PlusでOracle Databaseへの接続を確認できる
- C#からOracle Databaseへ接続するための準備ができる
- NuGetパッケージを追加できる
OracleConnectionを使ってDB接続できるOracleCommandを使ってSQL文を実行できるOracleDataReaderを使ってSELECT結果を読み取れるdepartments表のデータをC#から取得できるemployees表のデータをC#から取得できる- DBの
NULLをDBNull.Valueとして扱う必要があることを説明できる - SQLにパラメーターを渡して検索できる
- DB接続処理に例外処理を入れられる
- DB接続を安全に閉じるための
using文の役割を説明できる
本章で使用する環境
Section titled “本章で使用する環境”| 項目 | 内容 |
|---|---|
| 開発環境 | Visual Studio 2022 |
| プロジェクト種類 | コンソール アプリ |
| 対象フレームワーク | .NET 8 |
| プロジェクト名 | Chapter16_OracleConnection |
| DB | Oracle Database |
| 接続ユーザー | pingt |
| 主に使用する表 | departments、employees |
| 追加するNuGetパッケージ | Oracle.ManagedDataAccess.Core |
作業前チェック
Section titled “作業前チェック”作業を始める前に、次の内容を確認してください。
- Oracle Databaseが起動している
- SQL*Plusで
pingtユーザーに接続できる -
employees表をSELECTできる -
departments表をSELECTできる - Visual Studio 2022でコンソールアプリを作成できる
- NuGetパッケージを追加できる
-
try-catchを使える -
List<T>の基本を理解している -
nullとDBNull.Valueの違いをこれから意識して学習する準備ができている - 第15章の内容をGitに提出済みである
16-1 SQL*Plusで接続確認する
Section titled “16-1 SQL*Plusで接続確認する”まずSQL*Plusで確認する
Section titled “まずSQL*Plusで確認する”C#から接続する前に、まずSQL*PlusでOracle Databaseに接続できることを確認します。
コマンドプロンプトを開き、次のコマンドを実行します。
sqlplus pingt/oracle@//localhost:1521/XEPDB1接続できたら、次のSQL文を実行します。
SELECT USER FROM dual;実行結果例:
USER------------------------------PINGTPINGT と表示されれば、pingt ユーザーで接続できています。
departments表を確認する
Section titled “departments表を確認する”次に、departments 表を確認します。
SELECT department_id, department_name, manager_idFROM departmentsORDER BY department_id;実行結果例:
DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID------------- ------------------------------ ---------- 1 総務 1001 2 営業 1002 3 開発 1003 4 マーケティング 1004 5 品質管理 1005この結果が確認できれば、部署データを利用できます。
employees表を確認する
Section titled “employees表を確認する”次に、employees 表を確認します。
SELECT employee_id, employee_name, department_idFROM employeesORDER BY employee_id;実行結果例:
EMPLOYEE_ID EMPLOYEE_NAME DEPARTMENT_ID----------- ------------------------------ ------------- 1001 山田二郎 1 1002 佐藤昭夫 2 1003 山口洋子 3...この章では、まずC#からこれらの表をSELECTできることを目指します。
接続できない場合
Section titled “接続できない場合”SQL*Plusで接続できない場合、C#からも接続できません。
先に次の点を確認してください。
Oracle Databaseが起動しているか接続先が XEPDB1 でよいかユーザー名が pingt でよいかパスワードが oracle でよいかポート番号が 1521 でよいかC#のコードを書く前に、SQL*Plusでの接続確認を済ませておくことが重要です。
16-2 Visual Studioでプロジェクトを作成する
Section titled “16-2 Visual Studioでプロジェクトを作成する”コンソールアプリを作成する
Section titled “コンソールアプリを作成する”Visual Studio 2022を起動し、次の手順でプロジェクトを作成します。
1. 「新しいプロジェクトの作成」をクリックする2. 「コンソール アプリ」を選択する3. プロジェクト名に Chapter16_OracleConnection を入力する4. 保存場所を確認する5. フレームワークで .NET 8.0 を選択する6. 「作成」をクリックするプロジェクトが作成されたら、Program.cs を開きます。
まず通常の実行確認をする
Section titled “まず通常の実行確認をする”DB接続に入る前に、通常のコンソールアプリとして実行できることを確認します。
using System;
class Program{ static void Main() { Console.WriteLine("Oracle接続確認を開始します。"); }}実行結果:
Oracle接続確認を開始します。ここまで動作すれば、C#側のプロジェクト作成は問題ありません。
16-3 Oracle接続用のNuGetパッケージを追加する
Section titled “16-3 Oracle接続用のNuGetパッケージを追加する”NuGetパッケージとは
Section titled “NuGetパッケージとは”NuGetパッケージは、C#プロジェクトに機能を追加するための部品です。
Oracle Databaseに接続するためには、Oracle接続用のライブラリをプロジェクトに追加する必要があります。
この研修では、次のパッケージを使用します。
Oracle.ManagedDataAccess.Coreこのパッケージを追加すると、C#から次のようなクラスを使えるようになります。
OracleConnectionOracleCommandOracleDataReaderOracleExceptionVisual Studioから追加する
Section titled “Visual Studioから追加する”Visual Studioで次の手順を行います。
1. ソリューションエクスプローラーでプロジェクト名を右クリックする2. 「NuGet パッケージの管理」をクリックする3. 「参照」タブを開く4. 検索欄に Oracle.ManagedDataAccess.Core と入力する5. Oracle.ManagedDataAccess.Core を選択する6. 「インストール」をクリックする7. 確認画面が出たら内容を確認して進めるインストールが完了すると、Oracle接続用のクラスを利用できるようになります。
パッケージマネージャーコンソールで追加する場合
Section titled “パッケージマネージャーコンソールで追加する場合”Visual Studioのパッケージマネージャーコンソールを使う場合は、次のコマンドで追加できます。
Install-Package Oracle.ManagedDataAccess.Core研修では、基本的にはVisual Studioの画面操作で追加して構いません。
usingを追加する
Section titled “usingを追加する”Oracle接続用のクラスを使うために、Program.cs の先頭に次の using を追加します。
using Oracle.ManagedDataAccess.Client;最初は、次のような形になります。
using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { Console.WriteLine("Oracle接続確認を開始します。"); }}16-4 OracleConnectionで接続する
Section titled “16-4 OracleConnectionで接続する”接続文字列とは
Section titled “接続文字列とは”DBに接続するには、接続先やユーザー名、パスワードなどの情報が必要です。
これらをまとめた文字列を 接続文字列 と呼びます。
この研修環境では、まず次の接続文字列を使います。
string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";それぞれの意味は次の通りです。
| 項目 | 意味 |
|---|---|
User Id=pingt | 接続ユーザー |
Password=oracle | パスワード |
Data Source=localhost:1521/XEPDB1 | 接続先DB |
SQL*Plusでは、次のように接続していました。
sqlplus pingt/oracle@//localhost:1521/XEPDB1C#では、同じ情報を接続文字列として指定します。
接続確認コード
Section titled “接続確認コード”次のコードを入力して実行してください。
using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
Console.WriteLine("Oracle Databaseに接続しました。"); } } catch (OracleException ex) { Console.WriteLine("Oracle Databaseへの接続に失敗しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行結果例:
Oracle Databaseに接続しました。この表示が出れば、C#からOracle Databaseへ接続できています。
OracleConnectionとは
Section titled “OracleConnectionとは”OracleConnection は、Oracle Databaseへの接続を表すクラスです。
OracleConnection connection = new OracleConnection(connectionString);Open メソッドを呼び出すことで、実際にDBへ接続します。
connection.Open();接続に失敗した場合は、例外が発生します。
using文の役割
Section titled “using文の役割”次の部分に注目してください。
using (OracleConnection connection = new OracleConnection(connectionString)){ connection.Open();
Console.WriteLine("Oracle Databaseに接続しました。");}using 文を使うと、ブロックを抜けるときに接続を自動的に解放できます。
DB接続は、開いたままにしないことが重要です。
この章では、次のように理解してください。
using文 → 使い終わったら自動的に後片付けしてくれる書き方後のWebアプリやデスクトップアプリでも、DB接続を扱うときに重要になります。
接続できない場合の確認
Section titled “接続できない場合の確認”接続できない場合、エラーメッセージを確認します。
よくある原因は次の通りです。
| 原因 | 確認内容 |
|---|---|
| Oracle Databaseが起動していない | サービスやSQL*Plus接続を確認する |
| 接続文字列が間違っている | localhost:1521/XEPDB1 を確認する |
| ユーザー名が間違っている | pingt を確認する |
| パスワードが間違っている | oracle を確認する |
| NuGetパッケージが入っていない | Oracle.ManagedDataAccess.Core を確認する |
using が不足している | using Oracle.ManagedDataAccess.Client; を確認する |
環境によって接続文字列の Data Source に次のような書き方が必要になる場合もあります。
"User Id=pingt;Password=oracle;Data Source=//localhost:1521/XEPDB1;"まずは研修で指定された接続文字列を使い、接続できない場合は講師に確認してください。
16-5 SELECT文を実行する
Section titled “16-5 SELECT文を実行する”OracleCommandとは
Section titled “OracleCommandとは”DBに接続できたら、次はSQL文を実行します。
SQL文を実行するには、OracleCommand を使います。
OracleCommand command = new OracleCommand(sql, connection);sql には実行したいSQL文を指定します。
departments表をSELECTする
Section titled “departments表をSELECTする”まず、departments 表から部署一覧を取得します。
using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
string sql = @" SELECT department_id, department_name, manager_id FROM departments ORDER BY department_id";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
using (OracleCommand command = new OracleCommand(sql, connection)) using (OracleDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int departmentId = Convert.ToInt32(reader["department_id"]); string departmentName = reader["department_name"].ToString() ?? ""; int managerId = Convert.ToInt32(reader["manager_id"]);
Console.WriteLine($"{departmentId}:{departmentName}:管理者ID {managerId}"); } } } } catch (OracleException ex) { Console.WriteLine("Oracle Database処理中にエラーが発生しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行結果例:
1:総務:管理者ID 10012:営業:管理者ID 10023:開発:管理者ID 10034:マーケティング:管理者ID 10045:品質管理:管理者ID 1005SQL文字列の書き方
Section titled “SQL文字列の書き方”次のように、@ を付けると複数行の文字列を書きやすくなります。
string sql = @" SELECT department_id, department_name, manager_id FROM departments ORDER BY department_id";SQL文を複数行で書くと、読みやすくなります。
ExecuteReaderとは
Section titled “ExecuteReaderとは”ExecuteReader は、SELECT文を実行し、結果を読み取るための OracleDataReader を返します。
OracleDataReader reader = command.ExecuteReader();SELECT文の結果を1行ずつ読むには、Read メソッドを使います。
while (reader.Read()){ // 1行分のデータを読み取る}reader.Read() は、次の行があれば true、もう行がなければ false を返します。
列の値を取り出す
Section titled “列の値を取り出す”列の値は、列名を指定して取り出せます。
reader["department_id"]reader["department_name"]reader["manager_id"]ただし、取り出した値はそのままだと object 型として扱われます。
そのため、必要な型に変換します。
int departmentId = Convert.ToInt32(reader["department_id"]);string departmentName = reader["department_name"].ToString() ?? "";この章では、まず Convert.ToInt32 や ToString を使って値を取り出します。
16-6 employees表をSELECTする
Section titled “16-6 employees表をSELECTする”社員一覧を取得する
Section titled “社員一覧を取得する”次に、employees 表から社員一覧を取得します。
using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
string sql = @" SELECT employee_id, employee_name, hiredate, salary, department_id FROM employees ORDER BY employee_id";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
using (OracleCommand command = new OracleCommand(sql, connection)) using (OracleDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int employeeId = Convert.ToInt32(reader["employee_id"]); string employeeName = reader["employee_name"].ToString() ?? ""; DateTime hireDate = Convert.ToDateTime(reader["hiredate"]); int departmentId = Convert.ToInt32(reader["department_id"]);
Console.WriteLine( $"{employeeId}:{employeeName}:入社日 {hireDate.ToString("yyyy/MM/dd")}:部署ID {departmentId}" ); } } } } catch (OracleException ex) { Console.WriteLine("Oracle Database処理中にエラーが発生しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行結果例:
1001:山田二郎:入社日 2001/04/01:部署ID 11002:佐藤昭夫:入社日 2001/04/01:部署ID 21003:山口洋子:入社日 2001/10/01:部署ID 3...DateTimeとして取得する
Section titled “DateTimeとして取得する”hiredate はOracleの DATE 型です。
C#側では、DateTime として扱えます。
DateTime hireDate = Convert.ToDateTime(reader["hiredate"]);表示するときは、ToString で形式を指定できます。
hireDate.ToString("yyyy/MM/dd")第9章で学んだ日付書式がここで使えます。
給与を取得するときの注意
Section titled “給与を取得するときの注意”employees 表の salary には、NULL が入っている行があります。
そのため、次のように単純に変換すると、行によってはエラーになる可能性があります。
decimal salary = Convert.ToDecimal(reader["salary"]);DBの NULL は、C#では null とは少し違い、DBNull.Value として返されます。
次の節で、NULL の扱いを確認します。
16-7 DBのNULLを扱う
Section titled “16-7 DBのNULLを扱う”DBNull.Valueとは
Section titled “DBNull.Valueとは”Oracle Databaseの列に NULL が入っている場合、OracleDataReader で取り出した値は DBNull.Value になります。
たとえば、salary がNULLの行では、次の値が DBNull.Value になります。
reader["salary"]そのため、値を変換する前に DBNull.Value かどうかを確認します。
salaryがNULLか確認する
Section titled “salaryがNULLか確認する”次のコードでは、salary がNULLの場合に "未設定" と表示します。
using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
string sql = @" SELECT employee_id, employee_name, salary FROM employees ORDER BY employee_id";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
using (OracleCommand command = new OracleCommand(sql, connection)) using (OracleDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int employeeId = Convert.ToInt32(reader["employee_id"]); string employeeName = reader["employee_name"].ToString() ?? "";
string salaryText;
if (reader["salary"] == DBNull.Value) { salaryText = "未設定"; } else { decimal salary = Convert.ToDecimal(reader["salary"]); salaryText = $"{salary}円"; }
Console.WriteLine($"{employeeId}:{employeeName}:給与 {salaryText}"); } } } } catch (OracleException ex) { Console.WriteLine("Oracle Database処理中にエラーが発生しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行結果例:
1001:山田二郎:給与 500000円1002:佐藤昭夫:給与 500000円...1017:渡辺和也:給与 未設定1018:塚本孝:給与 未設定decimal?として扱う
Section titled “decimal?として扱う”DBのNULLをC#の null として扱いたい場合は、null許容型を使います。
decimal? salary;
if (reader["salary"] == DBNull.Value){ salary = null;}else{ salary = Convert.ToDecimal(reader["salary"]);}decimal? は、decimal の値または null を持てる型です。
第11章で学んだnull許容型がここで使われます。
yomiやcommissionもNULLになる可能性がある
Section titled “yomiやcommissionもNULLになる可能性がある”employees 表では、yomi や commission などもNULLになる可能性があります。
たとえば、yomi を取得する場合は次のように書けます。
string? yomi;
if (reader["yomi"] == DBNull.Value){ yomi = null;}else{ yomi = reader["yomi"].ToString();}commission を取得する場合は次のように書けます。
decimal? commission;
if (reader["commission"] == DBNull.Value){ commission = null;}else{ commission = Convert.ToDecimal(reader["commission"]);}DBから値を取得するときは、列がNULLになる可能性があるかを意識することが重要です。
NULL処理の整理
Section titled “NULL処理の整理”| DB側 | C#側での扱い |
|---|---|
NULL | DBNull.Value として返される |
NUMBER のNULL | int?、decimal? などで受ける |
VARCHAR2 のNULL | string? で受ける |
DATE のNULL | DateTime? で受ける |
この章では、まず次の形を覚えてください。
if (reader["列名"] == DBNull.Value){ // NULLの場合}else{ // 値がある場合}16-8 SQLに条件を渡す
Section titled “16-8 SQLに条件を渡す”文字列連結でSQLを作らない
Section titled “文字列連結でSQLを作らない”社員IDを指定して検索する場合、次のように文字列連結でSQLを作ることもできそうに見えます。
string sql = "SELECT employee_id, employee_name FROM employees WHERE employee_id = " + employeeId;しかし、このような書き方は避けます。
理由は、次のような問題があるためです。
SQL文が読みにくくなる文字列の扱いを間違えやすい不正な入力による危険があるSQLに値を渡す場合は、パラメーター を使います。
パラメーターを使った社員ID検索
Section titled “パラメーターを使った社員ID検索”次のコードでは、社員IDを入力し、該当する社員を検索します。
using System;using Oracle.ManagedDataAccess.Client;using Oracle.ManagedDataAccess.Types;
class Program{ static void Main() { Console.WriteLine("検索する社員IDを入力してください。");
string input = Console.ReadLine() ?? "";
if (!int.TryParse(input, out int employeeId)) { Console.WriteLine("社員IDは整数で入力してください。"); return; }
string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
string sql = @" SELECT employee_id, employee_name, department_id FROM employees WHERE employee_id = :employeeId";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
using (OracleCommand command = new OracleCommand(sql, connection)) { command.Parameters.Add("employeeId", OracleDbType.Int32).Value = employeeId;
using (OracleDataReader reader = command.ExecuteReader()) { if (reader.Read()) { int id = Convert.ToInt32(reader["employee_id"]); string name = reader["employee_name"].ToString() ?? ""; int departmentId = Convert.ToInt32(reader["department_id"]);
Console.WriteLine($"{id}:{name}:部署ID {departmentId}"); } else { Console.WriteLine("該当する社員は見つかりませんでした。"); } } } } } catch (OracleException ex) { Console.WriteLine("Oracle Database処理中にエラーが発生しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行例:
検索する社員IDを入力してください。10011001:山田二郎:部署ID 1該当しない場合:
検索する社員IDを入力してください。9999該当する社員は見つかりませんでした。パラメーターの書き方
Section titled “パラメーターの書き方”SQL文側では、値を入れたい場所に :employeeId のように書きます。
WHERE employee_id = :employeeIdC#側では、次のように値を設定します。
command.Parameters.Add("employeeId", OracleDbType.Int32).Value = employeeId;このようにすると、SQL文と値を分けて扱えます。
usingの追加について
Section titled “usingの追加について”パラメーターで OracleDbType.Int32 を使うため、次の using が必要です。
using Oracle.ManagedDataAccess.Client;環境やコードによっては、次の using も表示される場合があります。
using Oracle.ManagedDataAccess.Types;Visual Studioが不要と判断する場合もあります。
エラーが出る場合は、エラーメッセージを確認し、必要な using を追加してください。
16-9 JOINした結果を取得する
Section titled “16-9 JOINした結果を取得する”employeesとdepartmentsを結合する
Section titled “employeesとdepartmentsを結合する”SQL研修では、表を結合して情報を取得する方法も学びました。
ここでは、employees 表と departments 表を結合し、社員名と部署名を一緒に取得します。
SELECT e.employee_id, e.employee_name, d.department_nameFROM employees e JOIN departments d ON e.department_id = d.department_idORDER BY e.employee_idC#からJOIN結果を取得する
Section titled “C#からJOIN結果を取得する”using System;using Oracle.ManagedDataAccess.Client;
class Program{ static void Main() { string connectionString = "User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;";
string sql = @" SELECT e.employee_id, e.employee_name, d.department_name FROM employees e JOIN departments d ON e.department_id = d.department_id ORDER BY e.employee_id";
try { using (OracleConnection connection = new OracleConnection(connectionString)) { connection.Open();
using (OracleCommand command = new OracleCommand(sql, connection)) using (OracleDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int employeeId = Convert.ToInt32(reader["employee_id"]); string employeeName = reader["employee_name"].ToString() ?? ""; string departmentName = reader["department_name"].ToString() ?? "";
Console.WriteLine($"{employeeId}:{employeeName}:{departmentName}"); } } } } catch (OracleException ex) { Console.WriteLine("Oracle Database処理中にエラーが発生しました。"); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine("予期しないエラーが発生しました。"); Console.WriteLine(ex.Message); } }}実行結果例:
1001:山田二郎:総務1002:佐藤昭夫:営業1003:山口洋子:開発...SQL研修の知識がそのまま使える
Section titled “SQL研修の知識がそのまま使える”C#からDBへ接続しても、実行するSQL文そのものはSQL研修で学んだものです。
SELECTFROMWHEREORDER BYJOINC#側では、SQL文を文字列として用意し、OracleCommand で実行します。
C#の役割 → DBに接続する → SQL文を送る → 結果を受け取る → 画面に表示する、またはオブジェクトに変換する
SQLの役割 → 必要なデータを取得する → 条件で絞り込む → 並び替える → 表を結合するこの章では、まずSQLの結果をコンソールに表示しました。
次章では、取得した結果を Employee クラスや List<Employee> に変換して扱います。
よくあるつまずき
Section titled “よくあるつまずき”この章でよくあるつまずきを確認します。
| つまずき | 原因 | 対応 |
|---|---|---|
OracleConnection が見つからない | NuGetパッケージが入っていない | Oracle.ManagedDataAccess.Core を追加する |
OracleConnection が見つからない | using が不足している | using Oracle.ManagedDataAccess.Client; を追加する |
| DBに接続できない | Oracle Databaseが起動していない | SQL*Plusで接続確認する |
| DBに接続できない | 接続文字列が違う | User Id、Password、Data Source を確認する |
ORA- で始まるエラーが出る | Oracle側のエラー | エラー番号とメッセージを確認する |
| SELECT結果が表示されない | SQLの条件に一致するデータがない | SQL*Plusで同じSQLを実行して確認する |
DBNull.Value の処理で迷う | DBのNULLとC#のnullを混同している | reader["列名"] == DBNull.Value で確認する |
Convert.ToInt32 でエラーになる | NULLや想定外の値を変換している | 変換前にNULL確認する |
| SQL文が読みづらい | 文字列を1行に詰め込んでいる | @ を使って複数行で書く |
| 条件値を文字列連結してしまう | パラメーターの使い方に慣れていない | :employeeId と Parameters.Add を使う |
| 接続を閉じ忘れる | DB接続の後片付けを意識していない | using 文を使う |
学んだことチェック
Section titled “学んだことチェック”次の項目について、自分で説明できるか確認してください。
- SQL*Plusで
pingtユーザーに接続できる -
departments表をSQL*PlusでSELECTできる -
employees表をSQL*PlusでSELECTできる - C#プロジェクトにNuGetパッケージを追加できる
-
Oracle.ManagedDataAccess.Coreの役割を説明できる -
OracleConnectionの役割を説明できる - 接続文字列に含まれる情報を説明できる
-
connection.Open()でDB接続を開始できる -
OracleCommandでSQL文を実行できる -
OracleDataReaderでSELECT結果を1行ずつ読み取れる -
reader.Read()の役割を説明できる - 列名を指定して値を取り出せる
- DBのNULLを
DBNull.Valueとして確認できる - パラメーターを使ってSQLに条件を渡せる
-
try-catchでDB接続エラーに対応できる -
using文でDB接続を安全に閉じられる
研修の進め方によっては、隣の人または近くの人と説明確認を行います。
次の内容を、自分の言葉で説明してください。
- C#からOracle Databaseに接続する前に、なぜSQL*Plusで確認するのですか。
OracleConnectionは何をするクラスですか。- 接続文字列には、どのような情報が含まれていますか。
OracleCommandは何をするクラスですか。OracleDataReaderはどのように使いますか。reader.Read()は何をしていますか。- DBのNULLをC#で扱うとき、何に注意しますか。
- SQLに条件値を渡すとき、文字列連結ではなくパラメーターを使う理由は何ですか。
using文を使う理由は何ですか。
説明するときは、完全な答えでなくても構いません。
自分の言葉で説明しようとすることが大切です。
この章の演習課題に取り組みます。
制限時間は 90分 です。
時間内にすべて完成しなくても構いません。
できたところまでを保存し、Gitに提出してください。
提出について
制限時間になったら、完成・未完成に関わらず作業を止めます。 できたところまでをGitにcommitし、pushしてください。 未完成の場合は、どこまでできたかを報告できるようにしておきましょう。
まずは、全員が必須課題に取り組んでください。
課題16-1 SQL*Plusで接続確認する
Section titled “課題16-1 SQL*Plusで接続確認する”SQL*Plusで pingt ユーザーに接続し、現在のユーザーを確認してください。
実行するコマンド:
sqlplus pingt/oracle@//localhost:1521/XEPDB1実行するSQL:
SELECT USER FROM dual;条件:
PINGTと表示されることを確認する- 接続できない場合は、C#に進む前に講師に確認する
課題16-2 departments表をSQL*Plusで確認する
Section titled “課題16-2 departments表をSQL*Plusで確認する”SQL*Plusで次のSQLを実行してください。
SELECT department_id, department_name, manager_idFROM departmentsORDER BY department_id;条件:
- 部署一覧が表示されることを確認する
- 表示結果をメモしておく
課題16-3 C#からOracle Databaseに接続する
Section titled “課題16-3 C#からOracle Databaseに接続する”Visual Studioでコンソールアプリを作成し、C#からOracle Databaseに接続してください。
条件:
- プロジェクト名は
Chapter16_OracleConnectionとする - NuGetで
Oracle.ManagedDataAccess.Coreを追加する OracleConnectionを使う- 接続できたら
"Oracle Databaseに接続しました。"と表示する try-catchを使う
課題16-4 C#からdepartments表を表示する
Section titled “課題16-4 C#からdepartments表を表示する”C#から次のSQLを実行し、部署一覧を表示してください。
SELECT department_id, department_name, manager_idFROM departmentsORDER BY department_id実行結果例:
1:総務:管理者ID 10012:営業:管理者ID 10023:開発:管理者ID 10034:マーケティング:管理者ID 10045:品質管理:管理者ID 1005条件:
OracleCommandを使うOracleDataReaderを使うwhile (reader.Read())を使う- 列名を指定して値を取り出す
課題16-5 C#からemployees表を表示する
Section titled “課題16-5 C#からemployees表を表示する”C#から次のSQLを実行し、社員一覧を表示してください。
SELECT employee_id, employee_name, hiredate, department_idFROM employeesORDER BY employee_id実行結果例:
1001:山田二郎:入社日 2001/04/01:部署ID 11002:佐藤昭夫:入社日 2001/04/01:部署ID 2条件:
hiredateをDateTimeとして取得するToString("yyyy/MM/dd")で日付を表示するOracleDataReaderを使う
必須課題が終わった人は、発展課題に取り組んでください。
課題16-6 salaryのNULLを処理する
Section titled “課題16-6 salaryのNULLを処理する”employees 表から salary を取得し、NULLの場合は "未設定" と表示してください。
使用するSQL:
SELECT employee_id, employee_name, salaryFROM employeesORDER BY employee_id実行結果例:
1001:山田二郎:給与 500000円1017:渡辺和也:給与 未設定条件:
reader["salary"] == DBNull.Valueで確認する- NULLでない場合は
Convert.ToDecimalを使う - NULLの場合は
"未設定"と表示する
課題16-7 社員IDで検索する
Section titled “課題16-7 社員IDで検索する”社員IDを入力し、該当する社員を1件表示してください。
使用するSQL:
SELECT employee_id, employee_name, department_idFROM employeesWHERE employee_id = :employeeId実行例:
検索する社員IDを入力してください。10011001:山田二郎:部署ID 1該当しない場合:
該当する社員は見つかりませんでした。条件:
Console.ReadLineで社員IDを入力するint.TryParseで整数チェックする- SQLパラメーターを使う
- 文字列連結でSQLを作らない
reader.Read()の結果で見つかったかどうかを判定する
課題16-8 部署IDで社員を絞り込む
Section titled “課題16-8 部署IDで社員を絞り込む”部署IDを入力し、その部署に所属する社員を表示してください。
使用するSQL:
SELECT employee_id, employee_name, department_idFROM employeesWHERE department_id = :departmentIdORDER BY employee_id実行例:
検索する部署IDを入力してください。11001:山田二郎:部署ID 11006:佐々木明子:部署ID 1...条件:
- SQLパラメーターを使う
- 該当データが0件の場合は
"該当する社員は見つかりませんでした。"と表示する - 件数をカウントして表示してもよい
課題16-9 社員名で部分一致検索する
Section titled “課題16-9 社員名で部分一致検索する”社員名に入力キーワードが含まれる社員を表示してください。
使用するSQL:
SELECT employee_id, employee_name, department_idFROM employeesWHERE employee_name LIKE :keywordORDER BY employee_idC#側では、入力値の前後に % を付けます。
command.Parameters.Add("keyword", OracleDbType.Varchar2).Value = "%" + keyword + "%";実行例:
検索キーワードを入力してください。山1001:山田二郎:部署ID 11003:山口洋子:部署ID 3条件:
LIKEを使う- SQLパラメーターを使う
%を使って部分一致検索する
課題16-10 employeesとdepartmentsをJOINする
Section titled “課題16-10 employeesとdepartmentsをJOINする”C#から次のSQLを実行し、社員名と部署名を表示してください。
SELECT e.employee_id, e.employee_name, d.department_nameFROM employees e JOIN departments d ON e.department_id = d.department_idORDER BY e.employee_id実行結果例:
1001:山田二郎:総務1002:佐藤昭夫:営業1003:山口洋子:開発条件:
- JOINを使う
employee_id、employee_name、department_nameを表示する- SQL研修で学んだJOINがC#からも使えることを確認する
課題16-11 接続文字列をメソッドにまとめる
Section titled “課題16-11 接続文字列をメソッドにまとめる”接続文字列を返すメソッドを作成してください。
仕様:
static string GetConnectionString()戻り値:
"User Id=pingt;Password=oracle;Data Source=localhost:1521/XEPDB1;"条件:
- 接続文字列をコード内に何度も書かない
- DB接続処理では
GetConnectionString()を呼び出す - 後の章で設定ファイル化する可能性があることを意識する
Gitへの提出
Section titled “Gitへの提出”課題が終わったら、できたところまでをGitに提出します。
まず、現在の状態を確認します。
git status変更されたファイルを追加します。
git add .コミットします。
git commit -m "Chapter16 Oracle Database接続"ファイルサーバー上のリポジトリへpushします。
git pushGitの操作でエラーが出た場合は、自己判断で同じ操作を繰り返さず、講師に確認してください。
提出前チェックリスト
Section titled “提出前チェックリスト”提出前に、次の項目を確認してください。
- SQL*Plusで
pingtユーザーに接続できた -
departments表をSQL*Plusで確認できた -
employees表をSQL*Plusで確認できた - NuGetで
Oracle.ManagedDataAccess.Coreを追加した -
using Oracle.ManagedDataAccess.Client;を追加した -
OracleConnectionでDB接続できた -
OracleCommandでSELECT文を実行できた -
OracleDataReaderで結果を読み取れた -
using文で接続やReaderを閉じる形になっている -
try-catchで例外処理を入れている - DBのNULLを
DBNull.Valueで確認している - SQLパラメーターを使っている
- 文字列連結で条件付きSQLを作っていない
- インデントが整っている
- Gitにcommitしている
- Gitにpushしている
この章のまとめ
Section titled “この章のまとめ”この章では、C#のコンソールアプリからOracle Databaseに接続する方法を学習しました。
この章で学んだ主な内容は次の通りです。
- C#からDB接続する前に、SQL*Plusで接続確認する
- この研修では
pingtユーザーでOracle Databaseに接続する - Oracle接続用に
Oracle.ManagedDataAccess.CoreをNuGetで追加する OracleConnectionは、Oracle Databaseへの接続を表すOracleCommandは、SQL文を実行するために使うOracleDataReaderは、SELECT結果を1行ずつ読み取るために使うreader.Read()で次の行を読み取る- 列名を指定して値を取り出せる
- DBの
NULLは、C#ではDBNull.Valueとして扱う decimal?やstring?を使うと、DBのNULLをC#のnullとして扱いやすい- SQLに条件値を渡すときは、文字列連結ではなくパラメーターを使う
using文を使うと、DB接続やReaderを安全に後片付けできる- DB接続では、例外処理が重要である
- SQL研修で学んだSELECT、WHERE、ORDER BY、JOINは、C#から実行するSQLでもそのまま使える
次章では、DBデータをオブジェクトとして扱う ことを学習します。
この章では、SELECT結果をそのままコンソールに表示しました。
次章では、employees 表から取得した1行分のデータを Employee オブジェクトに変換し、複数行の結果を List<Employee> として扱います。
これにより、後のWebアプリやデスクトップアプリで、DBから取得したデータを画面に表示する準備が整います。