😊

netcoreapp3.1_x86プロジェクトでAdd-Migrationをしてエラー出た

2021/08/07に公開

はじめに

x86ビルドの.NET Core 3.1のWPFアプリを作っている

そのアプリの中でEntity Frameworkを使っている

Entity FrameworkのCLIコマンドでエラーが出て、一応解決したので、経緯を書き残す

なにが起きているか(=解決したいこと)

パッケージマネージャーからAdd-Migrationを実行するとエラーが出る。これを解消したい。

# エラーメッセージ
Could not load assembly 'project-name'. Ensure it is referenced by the startup project 'project-name'.

なにが起きているかの詳細

  • エラーが出るのはx86ビルドしたときのみであり、x64でビルドすればエラーは出ない
  • エラーが出るのはAdd-Migrationに限ったわけではない
  • 同列のコマンドであるGet-DbContextでも、まったく同じエラーが出る
  • Get-DbContext -vのように-vをつけると詳細が見れる)

似たようなIssueが報告されている

dotnet/efcoreのIssuesに似たエラーの報告が投稿されている

https://github.com/dotnet/efcore/issues/22594#issue-704195898

.NET5.NET Core 3.1の違いはあるのものの、IDEのエラーメッセージは同じだった

パッケージマネージャーコンソール
# 自分のVisualStudioが発したエラーメッセージ
PM> Get-DbContext
Build started...
Build succeeded.
Could not load assembly '2108_WPF_EFCore_x86'. Ensure it is referenced by the startup project '2108_WPF_EFCore_x86'.
# [意訳] プロジェクトのアセンブリが読み込めません。スタートアッププロジェクトから参照されていることを確認してください。

エラーメッセージの意味が分からない。スタートアッププロジェクトであるはずの2108_WPF_EFCore_x86が自分自身を参照できていないとは、どういうことなのか・・・?

Issueに解決方法へのリンクがある

意訳「dotnet efコマンドはdotnet.exeを内包しているから、ちゃんとSDKにパスを通してね」

https://github.com/dotnet/efcore/issues/14225#issuecomment-449461086

冒頭で試したAdd-Migrationdotnet efに置き換えて読み替えると、x86のSDKを入れればよさそう

先に結論

解決するための手順

  1. .NET5.0系 SDK (Windows x86) をインストールする
  2. 環境変数にパスを通す
  3. もし既存のx64版dotnet.exeのパスがある場合、インストールしたx86版dotnet.exeをx64版より上部に配置する

以下、キャプチャーなど含めて詳細に記載する

環境

  • Windows 10 Home
  • Visual Studio 2019 Community
  • .NET Core 3.1
  • Microsoft.EntityFrameworkCore 3.1.17
  • Microsoft.EntityFrameworkCore.Tools 3.1.17
csproj
<TargetFramework>netcoreapp3.1</TargetFramework>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.17">

検証のために新規プロジェクトをつくる

Entity Frameworkをつかうプロジェクトをサクッとつくる

WPF の使用を開始する - EF Core | Microsoft Docs」からコードを一部拝借する

MainWindow.xaml.cs
using Microsoft.EntityFrameworkCore;
using System.Windows;
namespace _2108_WPF_EFCore_x86
{
    public partial class MainWindow : Window
    {
        public MainWindow() => InitializeComponent();
    }
    public class Product
    {
        public int ProductId { get; set; }
        public string Name { get; set; }
    }
    public class ProductContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => base.OnConfiguring(optionsBuilder);
    }
}

動作の検証

起きている事象を再現する

パッケージマネージャーからGet-DbContextを実行する

Visual Studioでツール > NuGetパッケージマージャー > パッケージマネージャコンソールを開く

引数がいらないGet-DbContextをつかって、x86/x64の動作の違いを確認する
Add-Migrationは引数が必要)

x86はエラーが出る

対象プラットフォームとx86にしてGet-DbContextを実行すると、エラーが出る。これを解消したい。

パッケージマネージャーコンソール
# 再掲 x86
PM> Get-DbContext
Build started...
Build succeeded.
Could not load assembly '2108_WPF_EFCore_x86'. Ensure it is referenced by the startup project '2108_WPF_EFCore_x86'.
x64は正常に動く

対象プラットフォームとx64にしてGet-DbContextを実行すると、エラーは出ない

パッケージマネージャーコンソール
# x64
PM> Get-DbContext
Build started...
Build succeeded.

ProductContext

x86のSDKをインストールする

GitHub Issueの回答を参考に.NET5.0系 SDK (Windows x86) をインストールする

SDKをインストールする前の状態を確認する

.NET5系のSDKが2つインストールされていた

> dotnet --list-sdks
5.0.201 [C:\Program Files\dotnet\sdk]
5.0.301 [C:\Program Files\dotnet\sdk]

参照先(パスが通っている)のdotnet.exe

$ which dotnet
/c/Program Files/dotnet/dotnet
# Program Files(x86)ではない

(PowershellでWhichが使えなかったので、Git Bashで代用)

SDKをインストールする

.NET5.0系 SDK (Windows x86) をインストールする

.NET SDK 5.0.302がインストールされた

インストールしたSDKのパスを通す

システム > システムの詳細設定 > 環境変数 > システム環境変数 > Path > 編集 >C:\Program Files (x86)\dotnet\ > 上へ > 上へ > ...

インストール・パスを通したあとの状態

.NET5系のSDKが入っている
(.NET Core 3系は何かのタイミングでもともと入っていたと思われる)

> dotnet --list-sdks
3.1.411 [C:\Program Files (x86)\dotnet\sdk] # もともと入っていたっぽい
5.0.302 [C:\Program Files (x86)\dotnet\sdk] # こっちが新しく入ったほう

パスもx86のほうに通っている

$ which dotnet
/c/Program Files (x86)/dotnet/dotnet

最後に動作確認

x86でコマンドを打てば、所望の動きをする

おわりに

これだとx64には対応できないので、都度パスを変えないといけないのが面倒くさい・・・

おまけ

古いバージョンのSDKは必要か?

.NET SDK のより新しいリリースでは、通常、互換性を保ちながら、ランタイムの前バージョンを対象とするアプリケーションをビルドする機能が維持されます

Answer: 必要ない

バージョンを削除する必要はあるか

Discussion