あるSEのつぶやき・改

ITやシステム開発などの技術に関する話題を、取り上げたりしています。

.NET Core, アプリで使用するデータベースを実行環境で構築したり変更する方法

はじめに

.NET Core の調査を始めてから気になっていたのが、デプロイをどうするかという情報が極端に少ないことです。

開発に焦点があたりすぎていて、なかなかデプロイの情報にたどり着けません。

このブログでは以下の記事で .NET Core アプリのデプロイ方法のやり方の1つを提示しました。

そして、デプロイのもう1つの問題であるデータベースの構築(マイグレーション)があります。

データベースをどう初期構築するのか。そして、データベースに変更が入った時、問題なく更新できるのかということです。

今回は、PostgreSQL を使用するコンソールアプリケーションでその方法を見ていきましょう。

.NET Core コンソールアプリケーションの作成

.NET Core のコンソールアプリケーションをまず作成します。

今回はこんな感じで作成してみましょう。

$ dotnet new console -o ConsoleMigration

できあがったら Models フォルダ内に Person.cs と MyContext.cs を作成します(抜粋)。接続文字列はデプロイ環境のものを指定しています。

・Person.cs

public class Person
{
    public int Id {get ; set;}
    public string Name {get; set;}
}

・MyContext.cs

public class MyContext : DbContext
{
    public DbSet<Person> Person { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql(@"Server=localhost;Database=mydb;Username=postgres;Password=password;");
    }
}

そして、Program.cs を以下のように修正します。

    static void Main(string[] args)
    {
        using (var context = new MyContext())
        {
            context.Add(new Person{Name = "田中"});
            context.Add(new Person{Name = "佐藤"});
            context.Add(new Person{Name = "鈴木"});
            context.SaveChanges();
            
            foreach(var person in context.Person) {
                Console.WriteLine("Name:{0}", person.Name);
            }
        }
    }

.NET Core コンソールアプリケーションのデプロイ

.NET Core でデータベースを扱う場合は、プロジェクトの全てを Linux サーバーに上げなければいけないようです。

他の方法ではうまくいきませんでした。

プロジェクトの全てを Linux サーバーにアップロードする方法はいくつかありますが、私は tar.gz にかためて SFTP でアップロード後解凍しました。

プロジェクトの .csproj ファイルのあるディレクトリで以下のコマンドを実行して、データベースを作成します。

$ dotnet restore
$ dotnet ef migrations add init01
$ dotnet ef database update

これでデータベースとテーブルが作成されたので確認してみましょう。

$ psql -l
Password:
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 mydb      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres

mydb が正しく作成されていますね。

ではテーブルを確認してみます。

$ psql mydb
Password:
psql (9.6.8)
Type "help" for help.


mydb=> \d
                  List of relations
 Schema |         Name          |   Type   |  Owner
--------+-----------------------+----------+----------
 public | Person                | table    | postgres
 public | Person_Id_seq         | sequence | postgres
 public | __EFMigrationsHistory | table    | postgres
(3 rows)



mydb=> \d "Person"
                          Table "public.Person"
 Column |  Type   |                       Modifiers
--------+---------+-------------------------------------------------------
 Id     | integer | not null default nextval('"Person_Id_seq"'::regclass)
 Name   | text    |
Indexes:
    "PK_Person" PRIMARY KEY, btree ("Id")


mydb=>\q

問題ないですね。

.NET Core アプリケーションの実行

ここで .NET Core コンソールアプリケーションを実行して、データをテーブルに3件挿入後、読み込んで出力してみます。

$ dotnet build
$ dotnet run
Name:田中
Name:佐藤
Name:鈴木

問題なくデータが挿入されたようですね。一応、テーブルも確認してみましょう。ユーザーが postgres じゃないと select できないようなので、postgres ユーザーでログインします。

$ psql -U postgres mydb
Password for user postgres:
psql (9.6.8)
Type "help" for help.

mydb=# select * from "Person";
 Id | Name
----+------
  1 | 田中
  2 | 佐藤
  3 | 鈴木
(3 rows)

mydb=# \q

問題ありませんね。

モデル定義を変えた後のマイグレーション

この記事で確認したかったことの1つに、モデル(テーブル)定義を変えた際に既存のデータは残るのか、それとも消されるのかということででした。

Person.cs を以下のように変更します。

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

データベースに定義を反映します。

$ dotnet ef migrations add init02
$ dotnet ef database update

もう一度、select して結果を確認します。

mydb=# select * from "Person";
 Id | Name | Age
----+------+-----
  1 | 田中 |   0
  2 | 佐藤 |   0
  3 | 鈴木 |   0
(3 rows)

既存のデータが破壊されず、残した状態でテーブル定義が拡張されてますね。

すばらしい!

これで安心してコードファーストで開発をすることができます。

おわりに

.NET Core アプリケーションでデータベースを使用する場合、どのようにデータベースを構築すればよいのか。また、テーブル定義の変更時はどのような影響があるのかを見てきましたが、期待通りの動作で問題ないことが分かりました。

ソースコードをサーバーにまるごとアップロードしなければいけないのが少しイケてない気もしないでもないですが、Ruby on Rails で構築されている Mastodon も同じなのでそういうものなのかもしれません。

なんにせよ、懸念点がクリアされたのはよかったです。