😊

【.NET MAUI 】EntityFrameworkCore のマイグレーションができない時の対処法

2022/12/28に公開約3,000字

MAUI プロジェクトで EntityFrameworkCore を使おうとしたら一筋縄ではいかなかったのでメモ。

現象

MAUI プロジェクトにて、以下のチュートリアルに従って作業を進める。
https://learn.microsoft.com/ja-jp/ef/core/get-started/overview/first-app?tabs=netcore-cli

手順

  1. Microsoft.EntityFrameworkCore.Sqlite の Nuget パッケージを MAUI プロジェクトに追加
  2. Model.cs の作成
Model.cs
// using, 名前空間 は適宜

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    public string DbPath { get; }

    public BloggingContext()
    {
        var folder = Environment.SpecialFolder.LocalApplicationData;
        var path = Environment.GetFolderPath(folder);
        DbPath = System.IO.Path.Join(path, "blogging.db");
    }

    // The following configures EF to create a Sqlite database file in the
    // special "local" folder for your platform.
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite($"Data Source={DbPath}");
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}
  1. マイグレーション用のツール、パッケージを追加
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
  1. 初回マイグレーションの実行 dotnet ef migrations add InitialCreate ← ここで以下のようなエラーが発生
$ dotnet ef migrations add InitialCreate
Build started...
Build failed. Use dotnet build to see the errors.

原因

https://github.com/dotnet/maui/issues/9940#issuecomment-1238139207

こちらの GitHub の Issue のコメントによると、

  • マイグレーション時にアプリケーションコードを実行する必要アリ
  • 実行には .NET Core もしくは .NET Framework のランタイムが必要
    • ランライムはプロジェクトから借用
  • Xamarin などはランタイムが .NET Standard なのでダメ

とのことです。

解決方法

Model を別プロジェクト(クラスライブラリ)に切り出し、また別に、ツール実行用のコンソールプロジェクトを作成し、そのコンソールプロジェクトでマイグレーションを実行することで解決します。

別 issue ですがこちらを参考にしました。
https://github.com/microsoft/WindowsAppSDK/issues/2524#issuecomment-1129733373

手順

1. 〇〇.Model という名前のプロジェクト作成

〇〇(MAUIプロジェクト名).Model という名前のプロジェクトを同じソリューション内に作成し、そのプロジェクトに Model.cs を移動させます。

ただ移動させただけだと Microsoft.EntityFrameworkCore.Sqlite がないというエラーが出るので、必要なパッケージを NuGet マネージャから追加しておきます。

2. 不要なパッケージの削除、プロジェクト参照の追加

MAUI 側では EntityFrameworkCore のパッケージは必要なくなるので削除します。今回は、 Nuget マネージャから追加した Microsoft.EntityFrameworkCore.Sqlite と、コマンドラインから追加した Microsoft.EntityFrameworkCore.Design を削除します。

また、先ほど作成した 〇〇.Model プロジェクトへの参照を MAUI プロジェクトに追加します。

3. マイグレーション実行用のコンソールプロジェクトの作成

また新しく 〇〇.Console というプロジェクトを作成し、そのプロジェクトに 〇〇.Model へのプロジェクト参照と、Microsoft.EntityFrameworkCore.Tools の NuGet パッケージを追加します。

これで、マイグレーションのための準備は完了です。

4. マイグレーション実行

マイグレーションの実行は、ソリューションがあるディレクトリをカレントディレクトリにして、以下のように実行します。
対象プロジェクトに 〇〇.Model を、スタートアッププロジェクトに 〇〇.Console を指定するところがポイントです。

dotnet ef migrations add InitialCreate --project=MauiEfcore.Model --startup-project=MauiEfcore.Console

Discussion

ログインするとコメントできます