Skip to content

第16章 C#からOracle Databaseに接続する

この章では、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の NULLDBNull.Value として扱う必要があることを説明できる
  • SQLにパラメーターを渡して検索できる
  • DB接続処理に例外処理を入れられる
  • DB接続を安全に閉じるための using 文の役割を説明できる

項目内容
開発環境Visual Studio 2022
プロジェクト種類コンソール アプリ
対象フレームワーク.NET 8
プロジェクト名Chapter16_OracleConnection
DBOracle Database
接続ユーザーpingt
主に使用する表departmentsemployees
追加するNuGetパッケージOracle.ManagedDataAccess.Core

作業を始める前に、次の内容を確認してください。

  • Oracle Databaseが起動している
  • SQL*Plusで pingt ユーザーに接続できる
  • employees 表をSELECTできる
  • departments 表をSELECTできる
  • Visual Studio 2022でコンソールアプリを作成できる
  • NuGetパッケージを追加できる
  • try-catch を使える
  • List<T> の基本を理解している
  • nullDBNull.Value の違いをこれから意識して学習する準備ができている
  • 第15章の内容をGitに提出済みである

C#から接続する前に、まずSQL*PlusでOracle Databaseに接続できることを確認します。

コマンドプロンプトを開き、次のコマンドを実行します。

sqlplus pingt/oracle@//localhost:1521/XEPDB1

接続できたら、次のSQL文を実行します。

SELECT USER FROM dual;

実行結果例:

USER
------------------------------
PINGT

PINGT と表示されれば、pingt ユーザーで接続できています。


次に、departments 表を確認します。

SELECT department_id, department_name, manager_id
FROM departments
ORDER BY department_id;

実行結果例:

DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID
------------- ------------------------------ ----------
1 総務 1001
2 営業 1002
3 開発 1003
4 マーケティング 1004
5 品質管理 1005

この結果が確認できれば、部署データを利用できます。


次に、employees 表を確認します。

SELECT employee_id, employee_name, department_id
FROM employees
ORDER BY employee_id;

実行結果例:

EMPLOYEE_ID EMPLOYEE_NAME DEPARTMENT_ID
----------- ------------------------------ -------------
1001 山田二郎 1
1002 佐藤昭夫 2
1003 山口洋子 3
...

この章では、まずC#からこれらの表をSELECTできることを目指します。


SQL*Plusで接続できない場合、C#からも接続できません。

先に次の点を確認してください。

Oracle Databaseが起動しているか
接続先が XEPDB1 でよいか
ユーザー名が pingt でよいか
パスワードが oracle でよいか
ポート番号が 1521 でよいか

C#のコードを書く前に、SQL*Plusでの接続確認を済ませておくことが重要です。


16-2 Visual Studioでプロジェクトを作成する

Section titled “16-2 Visual Studioでプロジェクトを作成する”

Visual Studio 2022を起動し、次の手順でプロジェクトを作成します。

1. 「新しいプロジェクトの作成」をクリックする
2. 「コンソール アプリ」を選択する
3. プロジェクト名に Chapter16_OracleConnection を入力する
4. 保存場所を確認する
5. フレームワークで .NET 8.0 を選択する
6. 「作成」をクリックする

プロジェクトが作成されたら、Program.cs を開きます。


DB接続に入る前に、通常のコンソールアプリとして実行できることを確認します。

using System;
class Program
{
static void Main()
{
Console.WriteLine("Oracle接続確認を開始します。");
}
}

実行結果:

Oracle接続確認を開始します。

ここまで動作すれば、C#側のプロジェクト作成は問題ありません。


16-3 Oracle接続用のNuGetパッケージを追加する

Section titled “16-3 Oracle接続用のNuGetパッケージを追加する”

NuGetパッケージは、C#プロジェクトに機能を追加するための部品です。

Oracle Databaseに接続するためには、Oracle接続用のライブラリをプロジェクトに追加する必要があります。

この研修では、次のパッケージを使用します。

Oracle.ManagedDataAccess.Core

このパッケージを追加すると、C#から次のようなクラスを使えるようになります。

OracleConnection
OracleCommand
OracleDataReader
OracleException

Visual Studioで次の手順を行います。

1. ソリューションエクスプローラーでプロジェクト名を右クリックする
2. 「NuGet パッケージの管理」をクリックする
3. 「参照」タブを開く
4. 検索欄に Oracle.ManagedDataAccess.Core と入力する
5. Oracle.ManagedDataAccess.Core を選択する
6. 「インストール」をクリックする
7. 確認画面が出たら内容を確認して進める

インストールが完了すると、Oracle接続用のクラスを利用できるようになります。


パッケージマネージャーコンソールで追加する場合

Section titled “パッケージマネージャーコンソールで追加する場合”

Visual Studioのパッケージマネージャーコンソールを使う場合は、次のコマンドで追加できます。

Terminal window
Install-Package Oracle.ManagedDataAccess.Core

研修では、基本的にはVisual Studioの画面操作で追加して構いません。


Oracle接続用のクラスを使うために、Program.cs の先頭に次の using を追加します。

using Oracle.ManagedDataAccess.Client;

最初は、次のような形になります。

using System;
using Oracle.ManagedDataAccess.Client;
class Program
{
static void Main()
{
Console.WriteLine("Oracle接続確認を開始します。");
}
}

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/XEPDB1

C#では、同じ情報を接続文字列として指定します。


次のコードを入力して実行してください。

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 は、Oracle Databaseへの接続を表すクラスです。

OracleConnection connection = new OracleConnection(connectionString);

Open メソッドを呼び出すことで、実際にDBへ接続します。

connection.Open();

接続に失敗した場合は、例外が発生します。


次の部分に注目してください。

using (OracleConnection connection = new OracleConnection(connectionString))
{
connection.Open();
Console.WriteLine("Oracle Databaseに接続しました。");
}

using 文を使うと、ブロックを抜けるときに接続を自動的に解放できます。

DB接続は、開いたままにしないことが重要です。

この章では、次のように理解してください。

using文
→ 使い終わったら自動的に後片付けしてくれる書き方

後のWebアプリやデスクトップアプリでも、DB接続を扱うときに重要になります。


接続できない場合、エラーメッセージを確認します。

よくある原因は次の通りです。

原因確認内容
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;"

まずは研修で指定された接続文字列を使い、接続できない場合は講師に確認してください。


DBに接続できたら、次はSQL文を実行します。

SQL文を実行するには、OracleCommand を使います。

OracleCommand command = new OracleCommand(sql, connection);

sql には実行したいSQL文を指定します。


まず、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 1001
2:営業:管理者ID 1002
3:開発:管理者ID 1003
4:マーケティング:管理者ID 1004
5:品質管理:管理者ID 1005

次のように、@ を付けると複数行の文字列を書きやすくなります。

string sql = @"
SELECT department_id, department_name, manager_id
FROM departments
ORDER BY department_id";

SQL文を複数行で書くと、読みやすくなります。


ExecuteReader は、SELECT文を実行し、結果を読み取るための OracleDataReader を返します。

OracleDataReader reader = command.ExecuteReader();

SELECT文の結果を1行ずつ読むには、Read メソッドを使います。

while (reader.Read())
{
// 1行分のデータを読み取る
}

reader.Read() は、次の行があれば true、もう行がなければ false を返します。


列の値は、列名を指定して取り出せます。

reader["department_id"]
reader["department_name"]
reader["manager_id"]

ただし、取り出した値はそのままだと object 型として扱われます。

そのため、必要な型に変換します。

int departmentId = Convert.ToInt32(reader["department_id"]);
string departmentName = reader["department_name"].ToString() ?? "";

この章では、まず Convert.ToInt32ToString を使って値を取り出します。


次に、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 1
1002:佐藤昭夫:入社日 2001/04/01:部署ID 2
1003:山口洋子:入社日 2001/10/01:部署ID 3
...

hiredate はOracleの DATE 型です。

C#側では、DateTime として扱えます。

DateTime hireDate = Convert.ToDateTime(reader["hiredate"]);

表示するときは、ToString で形式を指定できます。

hireDate.ToString("yyyy/MM/dd")

第9章で学んだ日付書式がここで使えます。


employees 表の salary には、NULL が入っている行があります。

そのため、次のように単純に変換すると、行によってはエラーになる可能性があります。

decimal salary = Convert.ToDecimal(reader["salary"]);

DBの NULL は、C#では null とは少し違い、DBNull.Value として返されます。

次の節で、NULL の扱いを確認します。


Oracle Databaseの列に NULL が入っている場合、OracleDataReader で取り出した値は DBNull.Value になります。

たとえば、salary がNULLの行では、次の値が DBNull.Value になります。

reader["salary"]

そのため、値を変換する前に DBNull.Value かどうかを確認します。


次のコードでは、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:塚本孝:給与 未設定

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 表では、yomicommission なども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になる可能性があるかを意識することが重要です。


DB側C#側での扱い
NULLDBNull.Value として返される
NUMBER のNULLint?decimal? などで受ける
VARCHAR2 のNULLstring? で受ける
DATE のNULLDateTime? で受ける

この章では、まず次の形を覚えてください。

if (reader["列名"] == DBNull.Value)
{
// NULLの場合
}
else
{
// 値がある場合
}

社員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を入力してください。
1001
1001:山田二郎:部署ID 1

該当しない場合:

検索する社員IDを入力してください。
9999
該当する社員は見つかりませんでした。

SQL文側では、値を入れたい場所に :employeeId のように書きます。

WHERE employee_id = :employeeId

C#側では、次のように値を設定します。

command.Parameters.Add("employeeId", OracleDbType.Int32).Value = employeeId;

このようにすると、SQL文と値を分けて扱えます。


パラメーターで OracleDbType.Int32 を使うため、次の using が必要です。

using Oracle.ManagedDataAccess.Client;

環境やコードによっては、次の using も表示される場合があります。

using Oracle.ManagedDataAccess.Types;

Visual Studioが不要と判断する場合もあります。
エラーが出る場合は、エラーメッセージを確認し、必要な using を追加してください。


SQL研修では、表を結合して情報を取得する方法も学びました。

ここでは、employees 表と departments 表を結合し、社員名と部署名を一緒に取得します。

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

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研修で学んだものです。

SELECT
FROM
WHERE
ORDER BY
JOIN

C#側では、SQL文を文字列として用意し、OracleCommand で実行します。

C#の役割
→ DBに接続する
→ SQL文を送る
→ 結果を受け取る
→ 画面に表示する、またはオブジェクトに変換する
SQLの役割
→ 必要なデータを取得する
→ 条件で絞り込む
→ 並び替える
→ 表を結合する

この章では、まずSQLの結果をコンソールに表示しました。

次章では、取得した結果を Employee クラスや List<Employee> に変換して扱います。


この章でよくあるつまずきを確認します。

つまずき原因対応
OracleConnection が見つからないNuGetパッケージが入っていないOracle.ManagedDataAccess.Core を追加する
OracleConnection が見つからないusing が不足しているusing Oracle.ManagedDataAccess.Client; を追加する
DBに接続できないOracle Databaseが起動していないSQL*Plusで接続確認する
DBに接続できない接続文字列が違うUser IdPasswordData Source を確認する
ORA- で始まるエラーが出るOracle側のエラーエラー番号とメッセージを確認する
SELECT結果が表示されないSQLの条件に一致するデータがないSQL*Plusで同じSQLを実行して確認する
DBNull.Value の処理で迷うDBのNULLとC#のnullを混同しているreader["列名"] == DBNull.Value で確認する
Convert.ToInt32 でエラーになるNULLや想定外の値を変換している変換前にNULL確認する
SQL文が読みづらい文字列を1行に詰め込んでいる@ を使って複数行で書く
条件値を文字列連結してしまうパラメーターの使い方に慣れていない:employeeIdParameters.Add を使う
接続を閉じ忘れるDB接続の後片付けを意識していないusing 文を使う

次の項目について、自分で説明できるか確認してください。

  • 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接続を安全に閉じられる

研修の進め方によっては、隣の人または近くの人と説明確認を行います。

次の内容を、自分の言葉で説明してください。

  1. C#からOracle Databaseに接続する前に、なぜSQL*Plusで確認するのですか。
  2. OracleConnection は何をするクラスですか。
  3. 接続文字列には、どのような情報が含まれていますか。
  4. OracleCommand は何をするクラスですか。
  5. OracleDataReader はどのように使いますか。
  6. reader.Read() は何をしていますか。
  7. DBのNULLをC#で扱うとき、何に注意しますか。
  8. SQLに条件値を渡すとき、文字列連結ではなくパラメーターを使う理由は何ですか。
  9. 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_id
FROM departments
ORDER 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_id
FROM departments
ORDER BY department_id

実行結果例:

1:総務:管理者ID 1001
2:営業:管理者ID 1002
3:開発:管理者ID 1003
4:マーケティング:管理者ID 1004
5:品質管理:管理者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_id
FROM employees
ORDER BY employee_id

実行結果例:

1001:山田二郎:入社日 2001/04/01:部署ID 1
1002:佐藤昭夫:入社日 2001/04/01:部署ID 2

条件:

  • hiredateDateTime として取得する
  • ToString("yyyy/MM/dd") で日付を表示する
  • OracleDataReader を使う

必須課題が終わった人は、発展課題に取り組んでください。


employees 表から salary を取得し、NULLの場合は "未設定" と表示してください。

使用するSQL:

SELECT employee_id, employee_name, salary
FROM employees
ORDER BY employee_id

実行結果例:

1001:山田二郎:給与 500000円
1017:渡辺和也:給与 未設定

条件:

  • reader["salary"] == DBNull.Value で確認する
  • NULLでない場合は Convert.ToDecimal を使う
  • NULLの場合は "未設定" と表示する

社員IDを入力し、該当する社員を1件表示してください。

使用するSQL:

SELECT employee_id, employee_name, department_id
FROM employees
WHERE employee_id = :employeeId

実行例:

検索する社員IDを入力してください。
1001
1001:山田二郎:部署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_id
FROM employees
WHERE department_id = :departmentId
ORDER BY employee_id

実行例:

検索する部署IDを入力してください。
1
1001:山田二郎:部署ID 1
1006:佐々木明子:部署ID 1
...

条件:

  • SQLパラメーターを使う
  • 該当データが0件の場合は "該当する社員は見つかりませんでした。" と表示する
  • 件数をカウントして表示してもよい

課題16-9 社員名で部分一致検索する

Section titled “課題16-9 社員名で部分一致検索する”

社員名に入力キーワードが含まれる社員を表示してください。

使用するSQL:

SELECT employee_id, employee_name, department_id
FROM employees
WHERE employee_name LIKE :keyword
ORDER BY employee_id

C#側では、入力値の前後に % を付けます。

command.Parameters.Add("keyword", OracleDbType.Varchar2).Value = "%" + keyword + "%";

実行例:

検索キーワードを入力してください。
1001:山田二郎:部署ID 1
1003:山口洋子:部署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_name
FROM
employees e
JOIN departments d
ON e.department_id = d.department_id
ORDER BY
e.employee_id

実行結果例:

1001:山田二郎:総務
1002:佐藤昭夫:営業
1003:山口洋子:開発

条件:

  • JOINを使う
  • employee_idemployee_namedepartment_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に提出します。

まず、現在の状態を確認します。

Terminal window
git status

変更されたファイルを追加します。

Terminal window
git add .

コミットします。

Terminal window
git commit -m "Chapter16 Oracle Database接続"

ファイルサーバー上のリポジトリへpushします。

Terminal window
git push

Gitの操作でエラーが出た場合は、自己判断で同じ操作を繰り返さず、講師に確認してください。


提出前に、次の項目を確認してください。

  • 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している

この章では、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から取得したデータを画面に表示する準備が整います。