おーみんブログ

C#, ASP.NET Core, Unityが大好きです。

Docker上で動かしたASP.NET Coreアプリで"no such table: テーブル名"となる場合の対処法

はじめに

ASP.NET Core + SQLiteで自作したアプリをDocker上で動かした際に"no such table:テーブル名"と出た際の対処方法を備忘録として記載します。

エラー内容

Dockerfileをビルドし、docker run ~ でコンテナを作成していざアクセスした時でした。

fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT "t"."TestId", "t"."CreatedTime", "t"."Number", "t"."Title", "t"."UpdatedTime", "t"."UserId"
      FROM "Tests" AS "t"
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'DDD.Domain.Data.TestMakerContext'.
      Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Tests'.
         at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
         at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
         at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
         at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteReader()
・・・以下いっぱいのエラーログ

Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Tests'.」とありますので、どうやら対象のテーブルができていないようです。

対処法

以下のstackoverflowにも記載されていますが、DbContextのコンストラクタへ「Database.EnsureCreated();」を追記するとテーブルが作成されるとのことでした。

stackoverflow.com

ソースコードは以下のような感じになります。

public class TestMakerContext : DbContext
{
    public TestMakerContext (DbContextOptions<TestMakerContext> options)
        : base(options)
    {
        Database.EnsureCreated(); // <-- 追記
    }

    public DbSet<Test> Tests { get; set; }
    public DbSet<Question> Questions { get; set; }
    public DbSet<Choice> Choices { get; set; }
    public DbSet<User> Users { get; set; }
}

Database.EnsureCreated()とは?

データベースが存在しない場合は、EnsureCreated によって作成され、データベーススキーマが初期化されます。 テーブルが存在する場合 (別の DbContext クラスのテーブルを含む)、スキーマは初期化されません。

データベースが存在しない場合に良い感じに作ってくれるみたいです。

docs.microsoft.com

デメリット

この記事を書くにあたり、色々と調べていたらどうやらこの方法だとデータベースの移行(Migrate)には対応しないようですね・・・(;´∀`)

docs.microsoft.com

移行を考慮している際は上記の記事によると「Database.Migrate ()」を使用することを推奨しているので、そちらもいずれ動作確認してみようと思います。