🕌

【勉強メモ】DockerでOracleの環境構築 + .Net接続サンプル

2023/12/26に公開

はじめに

完全に個人用の勉強メモです。
Oracleの勉強の為に環境を立ち上げて色々いじってみようと思い立ちましたが、「ローカルの環境を汚したくなぁ」ってのと、「Dockerもついでに勉強しておくかぁ」ということで、ほぼこちらの記事(【Docker】Oracleを無料で簡単にローカルに構築する)を参考にしつつ、躓いたところをまとめたり、立ち上げた環境に対してC#(.Net)でアクセスしてみる所までをまとめました。

環境

  • Win11
  • Docker 24.0.6, build ed223bc
  • .NET 6
  • VisualStudio 2022

Docker環境構築

Dockerの環境構築に関しては参考記事の通りに進めていけば基本的に問題はありません。
使用するターミナルはgit bash以外が良いです。
理由は忘れました。後でちゃんと調べておきます。
しかし、PowerShellを使ったらあっさり解決したのは覚えています。

  • リポジトリのクローン
  • ORACLE EXPRESS EDITIONのダウンロード
  • リポジトリにダウンロードしたOracleを配置

ここまでは手順どおりで問題ありませんが、[イメージ作成シェルの実行]は参考コードでは動きません。
カレントディレクトリのパス指定は.\ではなく./が正解です。

./buildContainerImage.sh -v 21.3.0 -x -i

# 元のコード
.\buildContainerImage.sh -v 21.3.0 -x -i

後は引き続き参考サイトの通りにやれば良いです。

  • 生成物確認
    • docker images
  • ymlファイル作成
  • コンテナ作成 & 起動
    • docker-compose up -d

.NETから接続してみる

プロジェクト作成

  • ConsoleApp
  • .NET 6
  • トップレベルステートは使用しない

NuGet インストール

  • Dapper 2.1.24
  • Oracle.ManagedDataAccess.Core 3.21.120

簡単なサンプルなので、ChatGPTに作ってもらいました。
ただ、接続文字列はそのままでは使用できなかったため、少し修正しています。
それについては後半で解説します。

愚直に接続。
テーブルが存在しなければ作成するクエリを実行。
適当にデータを挿入。
単純にSELECTして表示。

サンプルコード
using Dapper;
using Oracle.ManagedDataAccess.Client;

namespace docker_oracle;

internal class Program
{
    static void Main(string[] args)
    {
        // 接続文字列
        string connectionString = "User Id=sys;Password=passw0rd;Connection Timeout=0;DBA Privilege=SYSDBA;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XEPDB1)));";

        // DB接続
        using OracleConnection db = new(connectionString);

        // テーブルの作成クエリ実行
        var createTableQuery = @"
                BEGIN
                    EXECUTE IMMEDIATE 'CREATE TABLE SampleTable (
                        Id NUMBER GENERATED BY DEFAULT AS IDENTITY,
                        Name VARCHAR2(100),
                        Age NUMBER
                    )';
                EXCEPTION
                    WHEN OTHERS THEN
                        IF SQLCODE != -955 THEN
                            RAISE;
                        END IF;
                END;";
        db.Execute(createTableQuery);

        // データの挿入
        var insertQuery = "INSERT INTO SampleTable (Name, Age) VALUES (:Name, :Age)";
        db.Execute(insertQuery, new { Name = "John Doe", Age = 30 });
        db.Execute(insertQuery, new { Name = "Hoge Fuga", Age = 25 });

        // データの選択
        var selectQuery = "SELECT * FROM SampleTable";
        var data = db.Query<SampleTable>(selectQuery);

        // データの表示
        foreach (var item in data)
        {
            Console.WriteLine($"ID: {item.Id}, Name: {item.Name}, Age: {(int)item.Age}");
        }
    }
}

public class SampleTable
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

次の接続文字列はChatGPTが一番最初に生成した物ですが、これでは接続できませんでした。
(エラーメッセージも残しておけばよかったです。)

"User Id=sys;Password=passw0rd;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)));";

試行錯誤の結果、接続文字列にConnection Timeout=0;DBA Privilege=SYSDBA;を含めることで接続することが出来ましたが、明らかに良くない書き方なので、あくまでサンプルとして見てください。
なぜダメなのかも後で調べておきます。

以下、接続がうまく行かない時に参考にしたサイト群

参考サイト

【Docker】Oracleを無料で簡単にローカルに構築する

GitHubで編集を提案

Discussion