やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Raspbian stretch MonoDevelop EntityFrameworkCore で SQLite3 を使えなかった2(Microsoft.Data.Sqlite.SqliteException: SQLite Error 1: 'no such table: *'.)

 情報少ない。

前回

 libe_sqlite3.soファイルを作成して実行ファイルのディレクトリに配置することで「System.DllNotFoundException: e_sqlite3」エラーは解決した。が、表題のエラーが解決できない。

対象環境

問題

 実行すると以下のエラーが出る。

Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.Sqlite.SqliteException: SQLite Error 1: 'no such table: Accounts'.

 ググってみる。

options.UseSqlite("Data Source=" + Path.Combine(ApplicationData.Current.LocalFolder.Path, "blogging.db"))

 ファイルパスは関係ないと思う。リンクされた以下を見てみる。

実行すると、モデルの最初のテーブルセットが作成されます。Add-Migration MyFirstMigration

Add-Migrationコマンドを実行する前に、ソリューションを手動でビルドする必要がある

 参考サイトにあった。

# Add-Migration 適当な名前
dotnet ef migrations add 適当な名前

 つまり、ビルド後にプロジェクトファイルがあるディレクトリで上記コマンドを実行すると、create tableSQL文が発行されるということか?

 やってみると、怒られた。

$ dotnet ef migrations add FirstMigration
Startup project 'HelloEFCoreSqlite.csproj' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the Entity Framework Core .NET Command-line Tools with this project, add an executable project targeting .NET Core or .NET Framework that references this project, and set it as the startup project using --startup-project; or, update this project to cross-target .NET Core or .NET Framework. For more information on using the EF Core Tools with .NET Standard projects, see https://go.microsoft.com/fwlink/?linkid=2034781

 スタートアッププロジェクトの.csprojがあるディレクトリで実行しろってことか? そっちに移動してやってみると以下エラー。

$ dotnet ef migrations add FirstMigration
Build failed.

 よくわからん。エラーメッセージにあったURLを見る。

 スタートアッププロジェクトを参照する起動引数があるっぽい。以下のようにして使うのか?

$ dotnet ef migrations add InitialCreate --startup-project /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj

 その前に整理しよう。まず、Eto.formsでソリューションを作成すると、以下のように2つのプロジェクトができる。

$ ls
HelloEFCoreSqlite  HelloEFCoreSqlite.Desktop

 このうち*.Desktopが実行(スタートアップ)側。

 dotnetコマンドでそれを参照させるということは、そっち側じゃないほうをカレントディレクトリにしてコマンド実行すればいいのかな?

$ cd /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite
$ dotnet ef migrations add InitialCreate --startup-project /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj
Build failed.

 同じく失敗……。どうしろと?

 参考サイトには以下のように書かれていた。プロジェクトファイルを修正する必要があるのか?

追加パッケージインストール後には.csprojを開いて入れたパッケージの参照タグの名前を"PackageReference"から"DotNetCliToolReference"に書き換える必要があります。

HelloCore.csproj

    <PackageReference Include="System.Text.Encoding.CodePages" Version="4.3.0" />
-   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
+   <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
  </ItemGroup>
</Project>

 だがMicrosoft.EntityFrameworkCore.Tools.DotNetはNuGetパッケージ追加で入れることができなかった。以下エラーになる。

Package Microsoft.EntityFrameworkCore.Tools.DotNet 2.0.3 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package Microsoft.EntityFrameworkCore.Tools.DotNet 2.0.3 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
...
Package 'Microsoft.EntityFrameworkCore.Tools.DotNet 2.0.3' has a package type 'DotnetCliTool' that is not supported by project 'HelloEFCoreSqlite'.

 .csprojに以下を追記すればいいのかな?

    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />
</ItemGroup>

.csproj<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />を追記した。MonoDevelopでビルドすると以下の警告が出た。

/home/pi/root/lib/.NETCore/2.2.101/sdk/2.2.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.ObsoleteReferences.targets(5,5): Warning NETSDK1059: The tool 'Microsoft.EntityFrameworkCore.Tools.DotNet' is now included in the .NET Core SDK. Information on resolving this warning is available at (https://aka.ms/dotnetclitools-in-box). (NETSDK1059) (HelloEFCoreSqlite)

 以下コマンドでDBを作成しようとするも同様に失敗した模様。

 $ dotnet ef migrations add InitialCreate --startup-project /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj
Build failed.

 ググってみた。

 -vオプションを付与すると詳細がみれるらしい。だが、標準出力するとなぜか空行がたくさんでた。しかたなくファイル出力した。

$ dotnet ef migrations add InitialCreate --startup-project /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj -v > log.txt

log.txt

Using project '/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.csproj'.
Using startup project '/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj'.
Writing '/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite/obj/HelloEFCoreSqlite.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=/tmp/tmpSFeO7c.tmp /verbosity:quiet /nologo /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.csproj
Writing '/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/obj/HelloEFCoreSqlite.Desktop.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=/tmp/tmpDhsZJp.tmp /verbosity:quiet /nologo /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj
dotnet build /tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj /verbosity:quiet /nologo
/home/pi/root/lib/.NETCore/2.2.101/sdk/2.2.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.ObsoleteReferences.targets(33,5): warning NETSDK1059: The tool 'Microsoft.EntityFrameworkCore.Tools.DotNet' is now included in the .NET Core SDK. Information on resolving this warning is available at (https://aka.ms/dotnetclitools-in-box). [/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.csproj]
/home/pi/root/lib/.NETCore/2.2.101/sdk/2.2.101/Microsoft.Common.CurrentVersion.targets(1179,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. [/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj]

Build FAILED.

/home/pi/root/lib/.NETCore/2.2.101/sdk/2.2.101/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.ObsoleteReferences.targets(33,5): warning NETSDK1059: The tool 'Microsoft.EntityFrameworkCore.Tools.DotNet' is now included in the .NET Core SDK. Information on resolving this warning is available at (https://aka.ms/dotnetclitools-in-box). [/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.csproj]
/home/pi/root/lib/.NETCore/2.2.101/sdk/2.2.101/Microsoft.Common.CurrentVersion.targets(1179,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. [/tmp/work/Projects/HelloEFCoreSqlite/HelloEFCoreSqlite/HelloEFCoreSqlite.Desktop/HelloEFCoreSqlite.Desktop.csproj]
    1 Warning(s)
    1 Error(s)

Time Elapsed 00:00:14.96
Microsoft.EntityFrameworkCore.Tools.CommandException: Build failed.
   at Microsoft.EntityFrameworkCore.Tools.Project.Build()
   at Microsoft.EntityFrameworkCore.Tools.RootCommand.Execute()
   at Microsoft.EntityFrameworkCore.Tools.Commands.CommandBase.<>c__DisplayClass0_0.<Configure>b__0()
   at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args)
   at Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args)
Build failed.

 おそらく以下の部分。

error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.6.1" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. 

 .NETFramework4.6.1が見つからないと。知らねーよ。EFCore使ってないときは動いていたのだから存在するはずでは? プロジェクトが複数だからこうなるのか? だめだ、何が問題なのかわからん。

ソースコード

 前回から変更されているファイルのみ抜粋。

MainForm.cs

 using句を使って解放するようにした。

using System;
using Eto.Forms;
using Eto.Drawing;

namespace HelloEFCoreSqlite
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            Title = "Hello EFCore 2.2 SQLite";
            ClientSize = new Size(400, 350);
            CreateDb();
        }
        private void CreateDb() {
            using (var db = new AppDbContext())
            {
                db.Accounts.Add(new Accounts() { Id=0, GitHubId=0, Username="user1", Password="pass1" });
                db.SaveChanges();
            }
        }
    }
}

AppDbContext.cs

 ファイルパスを絶対パスにした。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace HelloEFCoreSqlite
{
    public class AppDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlite(@"Data Source='/tmp/work/hello.db'");
        }
        public DbSet<Accounts> Accounts { get; set; }
    }
}

HelloEFCoreSqlite.csproj

 <DotNetCliToolReference ...を追記した。

<Project Sdk="Microsoft.NET.Sdk">
    
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RootNamespace>HelloEFCoreSqlite</RootNamespace>
    <PackageVersion>1.0</PackageVersion>
    <Title>HelloEFCoreSqlite</Title>
    <Copyright>Copyright © 2018</Copyright>
    <Description>Description of HelloEFCoreSqlite</Description>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Eto.Forms" Version="2.4.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
    <PackageReference Include="Microsoft.Data.Sqlite.Core" Version="2.2.0" />
    <PackageReference Include="SQLitePCLRaw.core" Version="1.1.11" />
    <PackageReference Include="SQLitePCLRaw.bundle_green" Version="1.1.11" />
    <PackageReference Include="SQLitePCLRaw.lib.e_sqlite3.linux" Version="1.1.11" />
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />
  </ItemGroup>
  
</Project>

所感

 dotnet ef migrations addコマンドがBuild failed.になるのが問題。どうすればいいの? コンソールプロジェクトでやり直すか。