C#(asp) docker環境でmigrationを利用する

[mac docker c# aspの環境を作成する](https://qiita.com/ziima/items/31f875bc8ca93ba22a12)の続き

## table of contents

0. docker環境を作る
0. dbupを依存関係を入れる
0. migrationファイルを作成する
0. migrationを実行する

## 1. docker 環境を作る

[mac docker c# aspの環境を作成する](https://qiita.com/ziima/items/31f875bc8ca93ba22a12)にpostgresqlとpgadminを追加していく。

[過去の遺物](https://qiita.com/ziima/items/0785a38234135a5025f0)を使い環境を構築。

```compose.yaml
services:
  api_container:
    container_name: api_container
    build:
      context: .
      dockerfile: tmp.dockerfile
    tty: true
    restart: always
    volumes:
      - .:/app
    ports:
      - 8080:5291
// ここから追記
    depends_on:
      postgresql:
        condition: service_healthy
  postgresql:
    container_name: postgresql_container
    build:
      context: database
      dockerfile: dockerfile
    tty: true
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_USER: example
      POSTGRES_DB: example
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U example"]
      interval: 1s
      timeout: 5s
      retries: 10
  admin:
    image: dpage/pgadmin4
    ports:
      - 1111:80
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: user@sample.com
      PGADMIN_DEFAULT_PASSWORD: password

volumes:
  pgdata: {}
  pgadmin_data: {}
// ここまで追記
```

```database/dockerfile
FROM postgres:16
```

上記を記載して、コマンドを実行。

```terminal
% docker compose up --build -d
```

## 2. dbupの依存関係を入れる

```terminal
% docker exec -it {ContainerId} bash
// make local.api.exec
// プロジェクトdirectoryに移動

% dotnet add package dbup-core
% dotnet add package dbup-postgresql
```

依存関係をいれて、とりあえずdone

## 3. migrationファイルを作成する

手順としては、
1. migratiaonファイルの作成
1. Program.csのファイルを更新
1. .csprojの更新

### 3-1. migratiaonファイルの作成

Scripts(なんでも良い)以下にファイルを生成する。(indexはってないけど、まぁいっか。)

```Scripts/0001.sql
CREATE TABLE users (
    id SERIAL NOT NULL,
    uuid UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    deleted_at TIMESTAMP,
    PRIMARY KEY (uuid)
);
```

### 3-2. Program.csのファイルを更新

```Program.cs
using DbUp;
using DbUp.Postgresql;
using System.Reflection;

// 中略

if (args.Contains("--migrate"))
{
    // compose.yamlに規定したものを利用する
    var connectionString = "Host=postgresql_container;User Id=example;Password=example;Database=example;Port=5432";
    MigrationExtensions migrationOperation = new MigrationExtensions(connectionString);
    migrationOperation.EnsureConnection();
    migrationOperation.RunMigrations();
}

// 別のファイルに切り出した方が管理しやすい
public class MigrationExtensions
    {
        private string connectionString;

        public MigrationExtensions(string connectionString) {
            this.connectionString = connectionString;
        }

        public void EnsureConnection()
        {
            EnsureDatabase.For.PostgresqlDatabase(this.connectionString);
        }

        public void RunMigrations()
        {
            try
            {
                var upgrader = DeployChanges.To
                    .PostgresqlDatabase(this.connectionString)
                    .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
                    .LogToConsole()
                    .Build();

                var result = upgrader.PerformUpgrade();

                if (result.Successful)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Migration Success!");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"Migration Failed: {result.Error}");
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"Migration Error: {ex.Message}");
            }
            finally
            {
                Console.ResetColor();
            }
        }
    }
```

### 3-3. .csprojの更新

```WebApi.csproj
<ItemGroup>
    // 中略

    <EmbeddedResource Include="Scripts\0001.sql" />
  </ItemGroup>
```

### 4. migrationを実行する

```terminal
$ dotnet watch --migrate
```

あとは、pgadminから確認する。

```
select * from information_schema.tables where table_schema = 'public';
```