netcoreapp3.1_x86プロジェクトでAdd-Migrationをしてエラー出た
はじめに
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に似たエラーの報告が投稿されている
.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にパスを通してね」
冒頭で試したAdd-Migration
をdotnet ef
に置き換えて読み替えると、x86のSDKを入れればよさそう
先に結論
解決するための手順
- .NET5.0系 SDK (Windows x86) をインストールする
- 環境変数にパスを通す
- もし既存の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
<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」からコードを一部拝借する
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